Bump packages to fix linter
This commit is contained in:
parent
ed9506bbaf
commit
0a11e3fdd9
6063 changed files with 378752 additions and 306784 deletions
24
node_modules/eslint/lib/api.js
generated
vendored
24
node_modules/eslint/lib/api.js
generated
vendored
|
|
@ -5,30 +5,22 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { CLIEngine } = require("./cli-engine");
|
||||
//-----------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const { ESLint } = require("./eslint");
|
||||
const { Linter } = require("./linter");
|
||||
const { RuleTester } = require("./rule-tester");
|
||||
const { SourceCode } = require("./source-code");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
Linter,
|
||||
CLIEngine,
|
||||
ESLint,
|
||||
RuleTester,
|
||||
SourceCode
|
||||
};
|
||||
|
||||
// DOTO: remove deprecated API.
|
||||
let deprecatedLinterInstance = null;
|
||||
|
||||
Object.defineProperty(module.exports, "linter", {
|
||||
enumerable: false,
|
||||
get() {
|
||||
if (!deprecatedLinterInstance) {
|
||||
deprecatedLinterInstance = new Linter();
|
||||
}
|
||||
|
||||
return deprecatedLinterInstance;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
101
node_modules/eslint/lib/cli-engine/cli-engine.js
generated
vendored
101
node_modules/eslint/lib/cli-engine/cli-engine.js
generated
vendored
|
|
@ -41,7 +41,7 @@ const hash = require("./hash");
|
|||
const LintResultCache = require("./lint-result-cache");
|
||||
|
||||
const debug = require("debug")("eslint:cli-engine");
|
||||
const validFixTypes = new Set(["problem", "suggestion", "layout"]);
|
||||
const validFixTypes = new Set(["directive", "problem", "suggestion", "layout"]);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Typedefs
|
||||
|
|
@ -51,12 +51,14 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
|
|||
/** @typedef {import("../shared/types").ConfigData} ConfigData */
|
||||
/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
|
||||
/** @typedef {import("../shared/types").LintMessage} LintMessage */
|
||||
/** @typedef {import("../shared/types").SuppressedLintMessage} SuppressedLintMessage */
|
||||
/** @typedef {import("../shared/types").ParserOptions} ParserOptions */
|
||||
/** @typedef {import("../shared/types").Plugin} Plugin */
|
||||
/** @typedef {import("../shared/types").RuleConf} RuleConf */
|
||||
/** @typedef {import("../shared/types").Rule} Rule */
|
||||
/** @typedef {ReturnType<CascadingConfigArrayFactory["getConfigArrayForFile"]>} ConfigArray */
|
||||
/** @typedef {ReturnType<ConfigArray["extractConfig"]>} ExtractedConfig */
|
||||
/** @typedef {import("../shared/types").FormatterFunction} FormatterFunction */
|
||||
/** @typedef {ReturnType<CascadingConfigArrayFactory.getConfigArrayForFile>} ConfigArray */
|
||||
/** @typedef {ReturnType<ConfigArray.extractConfig>} ExtractedConfig */
|
||||
|
||||
/**
|
||||
* The options to configure a CLI engine with.
|
||||
|
|
@ -91,7 +93,9 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
|
|||
* @typedef {Object} LintResult
|
||||
* @property {string} filePath The path to the file that was linted.
|
||||
* @property {LintMessage[]} messages All of the messages for the result.
|
||||
* @property {SuppressedLintMessage[]} suppressedMessages All of the suppressed messages for the result.
|
||||
* @property {number} errorCount Number of errors for the result.
|
||||
* @property {number} fatalErrorCount Number of fatal errors for the result.
|
||||
* @property {number} warningCount Number of warnings for the result.
|
||||
* @property {number} fixableErrorCount Number of fixable errors for the result.
|
||||
* @property {number} fixableWarningCount Number of fixable warnings for the result.
|
||||
|
|
@ -104,6 +108,7 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
|
|||
* @typedef {Object} LintReport
|
||||
* @property {LintResult[]} results All of the result.
|
||||
* @property {number} errorCount Number of errors for the result.
|
||||
* @property {number} fatalErrorCount Number of fatal errors for the result.
|
||||
* @property {number} warningCount Number of warnings for the result.
|
||||
* @property {number} fixableErrorCount Number of fixable errors for the result.
|
||||
* @property {number} fixableWarningCount Number of fixable warnings for the result.
|
||||
|
|
@ -261,6 +266,7 @@ function verifyText({
|
|||
const result = {
|
||||
filePath,
|
||||
messages,
|
||||
suppressedMessages: linter.getSuppressedMessages(),
|
||||
...calculateStatsPerFile(messages)
|
||||
};
|
||||
|
||||
|
|
@ -280,7 +286,7 @@ function verifyText({
|
|||
/**
|
||||
* Returns result with warning by ignore settings
|
||||
* @param {string} filePath File path of checked code
|
||||
* @param {string} baseDir Absolute path of base directory
|
||||
* @param {string} baseDir Absolute path of base directory
|
||||
* @returns {LintResult} Result with single warning
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -307,7 +313,9 @@ function createIgnoreResult(filePath, baseDir) {
|
|||
message
|
||||
}
|
||||
],
|
||||
suppressedMessages: [],
|
||||
errorCount: 0,
|
||||
fatalErrorCount: 0,
|
||||
warningCount: 1,
|
||||
fixableErrorCount: 0,
|
||||
fixableWarningCount: 0
|
||||
|
|
@ -331,6 +339,23 @@ function getRule(ruleId, configArrays) {
|
|||
return builtInRules.get(ruleId) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a message's rule type should be fixed.
|
||||
* @param {LintMessage} message The message to check.
|
||||
* @param {ConfigArray[]} lastConfigArrays The list of config arrays that the last `executeOnFiles` or `executeOnText` used.
|
||||
* @param {string[]} fixTypes An array of fix types to check.
|
||||
* @returns {boolean} Whether the message should be fixed.
|
||||
*/
|
||||
function shouldMessageBeFixed(message, lastConfigArrays, fixTypes) {
|
||||
if (!message.ruleId) {
|
||||
return fixTypes.has("directive");
|
||||
}
|
||||
|
||||
const rule = message.ruleId && getRule(message.ruleId, lastConfigArrays);
|
||||
|
||||
return Boolean(rule && rule.meta && fixTypes.has(rule.meta.type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect used deprecated rules.
|
||||
* @param {ConfigArray[]} usedConfigArrays The config arrays which were used.
|
||||
|
|
@ -341,9 +366,7 @@ function *iterateRuleDeprecationWarnings(usedConfigArrays) {
|
|||
|
||||
// Flatten used configs.
|
||||
/** @type {ExtractedConfig[]} */
|
||||
const configs = [].concat(
|
||||
...usedConfigArrays.map(getUsedExtractedConfigs)
|
||||
);
|
||||
const configs = usedConfigArrays.flatMap(getUsedExtractedConfigs);
|
||||
|
||||
// Traverse rule configs.
|
||||
for (const config of configs) {
|
||||
|
|
@ -391,7 +414,7 @@ function isErrorMessage(message) {
|
|||
* a directory or looks like a directory (ends in `path.sep`), in which case the file
|
||||
* name will be the `cacheFile/.cache_hashOfCWD`
|
||||
*
|
||||
* if cacheFile points to a file or looks like a file then in will just use that file
|
||||
* if cacheFile points to a file or looks like a file then it will just use that file
|
||||
* @param {string} cacheFile The name of file to be used to store the cache
|
||||
* @param {string} cwd Current working directory
|
||||
* @returns {string} the resolved path to the cache file
|
||||
|
|
@ -463,6 +486,7 @@ function getCacheFile(cacheFile, cwd) {
|
|||
* @param {string[]|null} keys The keys to assign true.
|
||||
* @param {boolean} defaultValue The default value for each property.
|
||||
* @param {string} displayName The property name which is used in error message.
|
||||
* @throws {Error} Requires array.
|
||||
* @returns {Record<string,boolean>} The boolean map.
|
||||
*/
|
||||
function toBooleanMap(keys, defaultValue, displayName) {
|
||||
|
|
@ -526,6 +550,7 @@ function createConfigDataFromOptions(options) {
|
|||
/**
|
||||
* Checks whether a directory exists at the given location
|
||||
* @param {string} resolvedPath A path from the CWD
|
||||
* @throws {Error} As thrown by `fs.statSync` or `fs.isDirectory`.
|
||||
* @returns {boolean} `true` if a directory exists
|
||||
*/
|
||||
function directoryExists(resolvedPath) {
|
||||
|
|
@ -543,13 +568,18 @@ function directoryExists(resolvedPath) {
|
|||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Core CLI.
|
||||
*/
|
||||
class CLIEngine {
|
||||
|
||||
/**
|
||||
* Creates a new instance of the core CLI engine.
|
||||
* @param {CLIEngineOptions} providedOptions The options for this instance.
|
||||
* @param {Object} [additionalData] Additional settings that are not CLIEngineOptions.
|
||||
* @param {Record<string,Plugin>|null} [additionalData.preloadedPlugins] Preloaded plugins.
|
||||
*/
|
||||
constructor(providedOptions) {
|
||||
constructor(providedOptions, { preloadedPlugins } = {}) {
|
||||
const options = Object.assign(
|
||||
Object.create(null),
|
||||
defaultOptions,
|
||||
|
|
@ -562,6 +592,13 @@ class CLIEngine {
|
|||
}
|
||||
|
||||
const additionalPluginPool = new Map();
|
||||
|
||||
if (preloadedPlugins) {
|
||||
for (const [id, plugin] of Object.entries(preloadedPlugins)) {
|
||||
additionalPluginPool.set(id, plugin);
|
||||
}
|
||||
}
|
||||
|
||||
const cacheFilePath = getCacheFile(
|
||||
options.cacheLocation || options.cacheFile,
|
||||
options.cwd
|
||||
|
|
@ -578,8 +615,8 @@ class CLIEngine {
|
|||
useEslintrc: options.useEslintrc,
|
||||
builtInRules,
|
||||
loadRules,
|
||||
eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
|
||||
eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
|
||||
getEslintRecommendedConfig: () => require("../../conf/eslint-recommended.js"),
|
||||
getEslintAllConfig: () => require("../../conf/eslint-all.js")
|
||||
});
|
||||
const fileEnumerator = new FileEnumerator({
|
||||
configArrayFactory,
|
||||
|
|
@ -623,12 +660,7 @@ class CLIEngine {
|
|||
const originalFix = (typeof options.fix === "function")
|
||||
? options.fix : () => true;
|
||||
|
||||
options.fix = message => {
|
||||
const rule = message.ruleId && getRule(message.ruleId, lastConfigArrays);
|
||||
const matches = rule && rule.meta && fixTypes.has(rule.meta.type);
|
||||
|
||||
return matches && originalFix(message);
|
||||
};
|
||||
options.fix = message => shouldMessageBeFixed(message, lastConfigArrays, fixTypes) && originalFix(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -654,11 +686,13 @@ class CLIEngine {
|
|||
|
||||
results.forEach(result => {
|
||||
const filteredMessages = result.messages.filter(isErrorMessage);
|
||||
const filteredSuppressedMessages = result.suppressedMessages.filter(isErrorMessage);
|
||||
|
||||
if (filteredMessages.length > 0) {
|
||||
filtered.push({
|
||||
...result,
|
||||
messages: filteredMessages,
|
||||
suppressedMessages: filteredSuppressedMessages,
|
||||
errorCount: filteredMessages.length,
|
||||
warningCount: 0,
|
||||
fixableErrorCount: result.fixableErrorCount,
|
||||
|
|
@ -681,26 +715,6 @@ class CLIEngine {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a plugin by passing its configuration
|
||||
* @param {string} name Name of the plugin.
|
||||
* @param {Plugin} pluginObject Plugin configuration object.
|
||||
* @returns {void}
|
||||
*/
|
||||
addPlugin(name, pluginObject) {
|
||||
const {
|
||||
additionalPluginPool,
|
||||
configArrayFactory,
|
||||
lastConfigArrays
|
||||
} = internalSlotsMap.get(this);
|
||||
|
||||
additionalPluginPool.set(name, pluginObject);
|
||||
configArrayFactory.clearCache();
|
||||
lastConfigArrays.length = 1;
|
||||
lastConfigArrays[0] = configArrayFactory.getConfigArrayForFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the patterns passed into executeOnFiles() into glob-based patterns
|
||||
* for easier handling.
|
||||
|
|
@ -730,6 +744,7 @@ class CLIEngine {
|
|||
/**
|
||||
* Executes the current configuration on an array of file and directory names.
|
||||
* @param {string[]} patterns An array of file and directory names.
|
||||
* @throws {Error} As may be thrown by `fs.unlinkSync`.
|
||||
* @returns {LintReport} The results for all files that were linted.
|
||||
*/
|
||||
executeOnFiles(patterns) {
|
||||
|
|
@ -936,6 +951,7 @@ class CLIEngine {
|
|||
* 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.
|
||||
* @throws {Error} If filepath a directory path.
|
||||
* @returns {ConfigData} A configuration object for the file.
|
||||
*/
|
||||
getConfigForFile(filePath) {
|
||||
|
|
@ -984,7 +1000,8 @@ class CLIEngine {
|
|||
* Returns the formatter representing the given format or null if the `format` is not a string.
|
||||
* @param {string} [format] The name of the format to load or the path to a
|
||||
* custom formatter.
|
||||
* @returns {(Function|null)} The formatter function or null if the `format` is not a string.
|
||||
* @throws {any} As may be thrown by requiring of formatter
|
||||
* @returns {(FormatterFunction|null)} The formatter function or null if the `format` is not a string.
|
||||
*/
|
||||
getFormatter(format) {
|
||||
|
||||
|
|
@ -1004,7 +1021,7 @@ class CLIEngine {
|
|||
let formatterPath;
|
||||
|
||||
// if there's a slash, then it's a file (TODO: this check seems dubious for scoped npm packages)
|
||||
if (!namespace && normalizedFormatName.indexOf("/") > -1) {
|
||||
if (!namespace && normalizedFormatName.includes("/")) {
|
||||
formatterPath = path.resolve(cwd, normalizedFormatName);
|
||||
} else {
|
||||
try {
|
||||
|
|
@ -1019,7 +1036,11 @@ class CLIEngine {
|
|||
try {
|
||||
return require(formatterPath);
|
||||
} catch (ex) {
|
||||
ex.message = `There was a problem loading formatter: ${formatterPath}\nError: ${ex.message}`;
|
||||
if (format === "table" || format === "codeframe") {
|
||||
ex.message = `The ${format} formatter is no longer part of core ESLint. Install it manually with \`npm install -D eslint-formatter-${format}\``;
|
||||
} else {
|
||||
ex.message = `There was a problem loading formatter: ${formatterPath}\nError: ${ex.message}`;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
||||
|
|
|
|||
17
node_modules/eslint/lib/cli-engine/file-enumerator.js
generated
vendored
17
node_modules/eslint/lib/cli-engine/file-enumerator.js
generated
vendored
|
|
@ -60,7 +60,7 @@ const IGNORED_SILENTLY = 1;
|
|||
const IGNORED = 2;
|
||||
|
||||
// For VSCode intellisense
|
||||
/** @typedef {ReturnType<CascadingConfigArrayFactory["getConfigArrayForFile"]>} ConfigArray */
|
||||
/** @typedef {ReturnType<CascadingConfigArrayFactory.getConfigArrayForFile>} ConfigArray */
|
||||
|
||||
/**
|
||||
* @typedef {Object} FileEnumeratorOptions
|
||||
|
|
@ -114,6 +114,7 @@ function isGlobPattern(pattern) {
|
|||
/**
|
||||
* Get stats of a given path.
|
||||
* @param {string} filePath The path to target file.
|
||||
* @throws {Error} As may be thrown by `fs.statSync`.
|
||||
* @returns {fs.Stats|null} The stats.
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -121,7 +122,8 @@ function statSafeSync(filePath) {
|
|||
try {
|
||||
return fs.statSync(filePath);
|
||||
} catch (error) {
|
||||
/* istanbul ignore next */
|
||||
|
||||
/* c8 ignore next */
|
||||
if (error.code !== "ENOENT") {
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -132,6 +134,7 @@ function statSafeSync(filePath) {
|
|||
/**
|
||||
* Get filenames in a given path to a directory.
|
||||
* @param {string} directoryPath The path to target directory.
|
||||
* @throws {Error} As may be thrown by `fs.readdirSync`.
|
||||
* @returns {import("fs").Dirent[]} The filenames.
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -139,7 +142,8 @@ function readdirSafeSync(directoryPath) {
|
|||
try {
|
||||
return fs.readdirSync(directoryPath, { withFileTypes: true });
|
||||
} catch (error) {
|
||||
/* istanbul ignore next */
|
||||
|
||||
/* c8 ignore next */
|
||||
if (error.code !== "ENOENT") {
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -173,7 +177,6 @@ function createExtensionRegExp(extensions) {
|
|||
*/
|
||||
class NoFilesFoundError extends Error {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {string} pattern The glob pattern which was not found.
|
||||
* @param {boolean} globDisabled If `true` then the pattern was a glob pattern, but glob was disabled.
|
||||
|
|
@ -190,7 +193,6 @@ class NoFilesFoundError extends Error {
|
|||
*/
|
||||
class AllFilesIgnoredError extends Error {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {string} pattern The glob pattern which was not found.
|
||||
*/
|
||||
|
|
@ -215,8 +217,8 @@ class FileEnumerator {
|
|||
cwd = process.cwd(),
|
||||
configArrayFactory = new CascadingConfigArrayFactory({
|
||||
cwd,
|
||||
eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
|
||||
eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
|
||||
getEslintRecommendedConfig: () => require("../../conf/eslint-recommended.js"),
|
||||
getEslintAllConfig: () => require("../../conf/eslint-all.js")
|
||||
}),
|
||||
extensions = null,
|
||||
globInputPaths = true,
|
||||
|
|
@ -270,6 +272,7 @@ class FileEnumerator {
|
|||
/**
|
||||
* Iterate files which are matched by given glob patterns.
|
||||
* @param {string|string[]} patternOrPatterns The glob patterns to iterate files.
|
||||
* @throws {NoFilesFoundError|AllFilesIgnoredError} On an unmatched pattern.
|
||||
* @returns {IterableIterator<FileAndConfig>} The found files.
|
||||
*/
|
||||
*iterateFiles(patternOrPatterns) {
|
||||
|
|
|
|||
138
node_modules/eslint/lib/cli-engine/formatters/codeframe.js
generated
vendored
138
node_modules/eslint/lib/cli-engine/formatters/codeframe.js
generated
vendored
|
|
@ -1,138 +0,0 @@
|
|||
/**
|
||||
* @fileoverview Codeframe reporter
|
||||
* @author Vitor Balocco
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const chalk = require("chalk");
|
||||
const { codeFrameColumns } = require("@babel/code-frame");
|
||||
const path = require("path");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Given a word and a count, append an s if count is not one.
|
||||
* @param {string} word A word in its singular form.
|
||||
* @param {number} count A number controlling whether word should be pluralized.
|
||||
* @returns {string} The original word with an s on the end if count is not one.
|
||||
*/
|
||||
function pluralize(word, count) {
|
||||
return (count === 1 ? word : `${word}s`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a formatted relative file path from an absolute path and a line/column in the file.
|
||||
* @param {string} filePath The absolute file path to format.
|
||||
* @param {number} line The line from the file to use for formatting.
|
||||
* @param {number} column The column from the file to use for formatting.
|
||||
* @returns {string} The formatted file path.
|
||||
*/
|
||||
function formatFilePath(filePath, line, column) {
|
||||
let relPath = path.relative(process.cwd(), filePath);
|
||||
|
||||
if (line && column) {
|
||||
relPath += `:${line}:${column}`;
|
||||
}
|
||||
|
||||
return chalk.green(relPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatted output for a given message.
|
||||
* @param {Object} message The object that represents this message.
|
||||
* @param {Object} parentResult The result object that this message belongs to.
|
||||
* @returns {string} The formatted output.
|
||||
*/
|
||||
function formatMessage(message, parentResult) {
|
||||
const type = (message.fatal || message.severity === 2) ? chalk.red("error") : chalk.yellow("warning");
|
||||
const msg = `${chalk.bold(message.message.replace(/([^ ])\.$/u, "$1"))}`;
|
||||
const ruleId = message.fatal ? "" : chalk.dim(`(${message.ruleId})`);
|
||||
const filePath = formatFilePath(parentResult.filePath, message.line, message.column);
|
||||
const sourceCode = parentResult.output ? parentResult.output : parentResult.source;
|
||||
|
||||
const firstLine = [
|
||||
`${type}:`,
|
||||
`${msg}`,
|
||||
ruleId ? `${ruleId}` : "",
|
||||
sourceCode ? `at ${filePath}:` : `at ${filePath}`
|
||||
].filter(String).join(" ");
|
||||
|
||||
const result = [firstLine];
|
||||
|
||||
if (sourceCode) {
|
||||
result.push(
|
||||
codeFrameColumns(sourceCode, { start: { line: message.line, column: message.column } }, { highlightCode: false })
|
||||
);
|
||||
}
|
||||
|
||||
return result.join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatted output summary for a given number of errors and warnings.
|
||||
* @param {number} errors The number of errors.
|
||||
* @param {number} warnings The number of warnings.
|
||||
* @param {number} fixableErrors The number of fixable errors.
|
||||
* @param {number} fixableWarnings The number of fixable warnings.
|
||||
* @returns {string} The formatted output summary.
|
||||
*/
|
||||
function formatSummary(errors, warnings, fixableErrors, fixableWarnings) {
|
||||
const summaryColor = errors > 0 ? "red" : "yellow";
|
||||
const summary = [];
|
||||
const fixablesSummary = [];
|
||||
|
||||
if (errors > 0) {
|
||||
summary.push(`${errors} ${pluralize("error", errors)}`);
|
||||
}
|
||||
|
||||
if (warnings > 0) {
|
||||
summary.push(`${warnings} ${pluralize("warning", warnings)}`);
|
||||
}
|
||||
|
||||
if (fixableErrors > 0) {
|
||||
fixablesSummary.push(`${fixableErrors} ${pluralize("error", fixableErrors)}`);
|
||||
}
|
||||
|
||||
if (fixableWarnings > 0) {
|
||||
fixablesSummary.push(`${fixableWarnings} ${pluralize("warning", fixableWarnings)}`);
|
||||
}
|
||||
|
||||
let output = chalk[summaryColor].bold(`${summary.join(" and ")} found.`);
|
||||
|
||||
if (fixableErrors || fixableWarnings) {
|
||||
output += chalk[summaryColor].bold(`\n${fixablesSummary.join(" and ")} potentially fixable with the \`--fix\` option.`);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = function(results) {
|
||||
let errors = 0;
|
||||
let warnings = 0;
|
||||
let fixableErrors = 0;
|
||||
let fixableWarnings = 0;
|
||||
|
||||
const resultsWithMessages = results.filter(result => result.messages.length > 0);
|
||||
|
||||
let output = resultsWithMessages.reduce((resultsOutput, result) => {
|
||||
const messages = result.messages.map(message => `${formatMessage(message, result)}\n\n`);
|
||||
|
||||
errors += result.errorCount;
|
||||
warnings += result.warningCount;
|
||||
fixableErrors += result.fixableErrorCount;
|
||||
fixableWarnings += result.fixableWarningCount;
|
||||
|
||||
return resultsOutput.concat(messages);
|
||||
}, []).join("\n");
|
||||
|
||||
output += "\n";
|
||||
output += formatSummary(errors, warnings, fixableErrors, fixableWarnings);
|
||||
|
||||
return (errors + warnings) > 0 ? output : "";
|
||||
};
|
||||
46
node_modules/eslint/lib/cli-engine/formatters/formatters-meta.json
generated
vendored
Normal file
46
node_modules/eslint/lib/cli-engine/formatters/formatters-meta.json
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
[
|
||||
{
|
||||
"name": "checkstyle",
|
||||
"description": "Outputs results to the [Checkstyle](https://checkstyle.sourceforge.io/) format."
|
||||
},
|
||||
{
|
||||
"name": "compact",
|
||||
"description": "Human-readable output format. Mimics the default output of JSHint."
|
||||
},
|
||||
{
|
||||
"name": "html",
|
||||
"description": "Outputs results to HTML. The `html` formatter is useful for visual presentation in the browser."
|
||||
},
|
||||
{
|
||||
"name": "jslint-xml",
|
||||
"description": "Outputs results to format compatible with the [JSLint Jenkins plugin](https://plugins.jenkins.io/jslint/)."
|
||||
},
|
||||
{
|
||||
"name": "json-with-metadata",
|
||||
"description": "Outputs JSON-serialized results. The `json-with-metadata` provides the same linting results as the [`json`](#json) formatter with additional metadata about the rules applied. The linting results are included in the `results` property and the rules metadata is included in the `metadata` property.\n\nAlternatively, you can use the [ESLint Node.js API](../../integrate/nodejs-api) to programmatically use ESLint."
|
||||
},
|
||||
{
|
||||
"name": "json",
|
||||
"description": "Outputs JSON-serialized results. The `json` formatter is useful when you want to programmatically work with the CLI's linting results.\n\nAlternatively, you can use the [ESLint Node.js API](../../integrate/nodejs-api) to programmatically use ESLint."
|
||||
},
|
||||
{
|
||||
"name": "junit",
|
||||
"description": "Outputs results to format compatible with the [JUnit Jenkins plugin](https://plugins.jenkins.io/junit/)."
|
||||
},
|
||||
{
|
||||
"name": "stylish",
|
||||
"description": "Human-readable output format. This is the default formatter."
|
||||
},
|
||||
{
|
||||
"name": "tap",
|
||||
"description": "Outputs results to the [Test Anything Protocol (TAP)](https://testanything.org/) specification format."
|
||||
},
|
||||
{
|
||||
"name": "unix",
|
||||
"description": "Outputs results to a format similar to many commands in UNIX-like systems. Parsable with tools such as [grep](https://www.gnu.org/software/grep/manual/grep.html), [sed](https://www.gnu.org/software/sed/manual/sed.html), and [awk](https://www.gnu.org/software/gawk/manual/gawk.html)."
|
||||
},
|
||||
{
|
||||
"name": "visualstudio",
|
||||
"description": "Outputs results to format compatible with the integrated terminal of the [Visual Studio](https://visualstudio.microsoft.com/) IDE. When using Visual Studio, you can click on the linting results in the integrated terminal to go to the issue in the source code."
|
||||
}
|
||||
]
|
||||
147
node_modules/eslint/lib/cli-engine/formatters/html.js
generated
vendored
147
node_modules/eslint/lib/cli-engine/formatters/html.js
generated
vendored
|
|
@ -39,87 +39,114 @@ function pageTemplate(it) {
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ESLint Report</title>
|
||||
<link rel="icon" type="image/png" sizes="any" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAHaAAAB2gGFomX7AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAABD1JREFUWMPFl11sk2UUx3/nbYtjxS1MF7MLMTECMgSTtSSyrQkLhAj7UBPnDSEGoxegGzMwojhXVpmTAA5iYpSoMQa8GBhFOrMFk03buei6yRAlcmOM0SEmU9d90b19jxcM1o5+sGnsc/e+z/l6ztf/HFFVMnns6QieeOCHBePGsHM+wrOtvLG2C4WRVDSSygNV7sCjlspxwDnPB44aols/DXk+mbMBmx/6OseITF1CuOtfevkPh2Uu+/jbdX8lujSScRlT5r7/QDlAfsRmfzmpnkQ/H3H13gf6bBrBn1uqK8WylgEnU8eZmk1repbfchJG1TyKyIKEwuBHFd3lD3naY3O1siiwXsVoBV2VgM1ht/QQUJk2ByqKghsQziYQ8ifKgexIXmuyzC4r67Y7R+xPAfuB/Nn3Cpva+0s7khpQVtZtd4bt51BWxtBYAiciprG7c7D4SixzU9PYalDL6110Ifb/w8W9eY7JqFeFHbO8fPGyLHwwFHJNJTSgwtVTB9oaw9BlQ+tO93vOxypoaQnfEYlI43SeCHDC4TDq9+51/h5fxr33q0ZfV9g04wat9Q943rjJgCp3952W2i8Bi6eDvdsfKj0cK/DYMRyXL4/sUJUmIHd2zYMezsvLaamp4WpcWN3BXSiHpuMwbGbZlnZ8tXY4rgosy+G7oRwQ0cAsd28YGgqfU5UjCZQDLALxDg+Hv/P5Rqvj4hwrS8izXzWb4spwc1GgENFnkpWRzxeuB+ssUHgLdb9UVdt8vpGdKQpze7n7y1U3DBChNRUuqOo9c+0+qpKKxyZqtAIYla7gY4JszAAQri93BSsMRZoyBcUC+w3Q3AyOA4sNhAOZ0q7Iq0b2vUNvK5zPgP+/H8+Zetdoa6uOikhdGurxebwvJY8Iz3V1rTMNAH+opEuQj5KTT/qA1yC+wyUjBm12OidaUtCcPNNX2h0Hx2JG69VulANZAJZJwfU7rzd/FHixuXniTdM0m4GtSQT7bTartqEh9yfImUEzkwKZmTwmo5a5JwkYBfcDL01/RkR5y8iWhtPBknB8ZxwtU9UjwOrrKCeizzc25nTGg1F/turEHoU9wMLpDvWKf8DTmNCAKnd/tqUTF4ElMXJ+A5rWDJS+41WsGWzALhJ+ErBWrLj9g+pqojHxlXJX8HGUg0BsR/x1yhxf3jm4cSzpQFLp6tmi6PEE7g1ZhtZ91ufpSZUAFa6gC+UoQslNaSmypT1U8mHKiUgEKS8KfgF4EpYunFI16tsHin+OG0LcgQK7yj7g6cSzpva2D3hKVNG0Y3mVO1BkqfSlmJrHBQ4uvM12gJHc6ETW8HZVfMRmXvyxxNC1Z/o839zyXlDuCr4nsC11J+MXueaVJWn6yPv+/pJtc9oLTNN4AeTvNGByd3rlhE2x9s5pLwDoHCy+grDzWmOZ95lUtLYj5Bma126Y8eX0/zj/ADxGyViSg4BXAAAAAElFTkSuQmCC">
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PScwIDAgMjk0LjgyNSAyNTguOTgyJyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnPg0KPHBhdGggZmlsbD0nIzgwODBGMicgZD0nTTk3LjAyMSw5OS4wMTZsNDguNDMyLTI3Ljk2MmMxLjIxMi0wLjcsMi43MDYtMC43LDMuOTE4LDBsNDguNDMzLDI3Ljk2MiBjMS4yMTEsMC43LDEuOTU5LDEuOTkzLDEuOTU5LDMuMzkzdjU1LjkyNGMwLDEuMzk5LTAuNzQ4LDIuNjkzLTEuOTU5LDMuMzk0bC00OC40MzMsMjcuOTYyYy0xLjIxMiwwLjctMi43MDYsMC43LTMuOTE4LDAgbC00OC40MzItMjcuOTYyYy0xLjIxMi0wLjctMS45NTktMS45OTQtMS45NTktMy4zOTR2LTU1LjkyNEM5NS4wNjMsMTAxLjAwOSw5NS44MSw5OS43MTYsOTcuMDIxLDk5LjAxNicvPg0KPHBhdGggZmlsbD0nIzRCMzJDMycgZD0nTTI3My4zMzYsMTI0LjQ4OEwyMTUuNDY5LDIzLjgxNmMtMi4xMDItMy42NC01Ljk4NS02LjMyNS0xMC4xODgtNi4zMjVIODkuNTQ1IGMtNC4yMDQsMC04LjA4OCwyLjY4NS0xMC4xOSw2LjMyNWwtNTcuODY3LDEwMC40NWMtMi4xMDIsMy42NDEtMi4xMDIsOC4yMzYsMCwxMS44NzdsNTcuODY3LDk5Ljg0NyBjMi4xMDIsMy42NCw1Ljk4Niw1LjUwMSwxMC4xOSw1LjUwMWgxMTUuNzM1YzQuMjAzLDAsOC4wODctMS44MDUsMTAuMTg4LTUuNDQ2bDU3Ljg2Ny0xMDAuMDEgQzI3NS40MzksMTMyLjM5NiwyNzUuNDM5LDEyOC4xMjgsMjczLjMzNiwxMjQuNDg4IE0yMjUuNDE5LDE3Mi44OThjMCwxLjQ4LTAuODkxLDIuODQ5LTIuMTc0LDMuNTlsLTczLjcxLDQyLjUyNyBjLTEuMjgyLDAuNzQtMi44ODgsMC43NC00LjE3LDBsLTczLjc2Ny00Mi41MjdjLTEuMjgyLTAuNzQxLTIuMTc5LTIuMTA5LTIuMTc5LTMuNTlWODcuODQzYzAtMS40ODEsMC44ODQtMi44NDksMi4xNjctMy41OSBsNzMuNzA3LTQyLjUyN2MxLjI4Mi0wLjc0MSwyLjg4Ni0wLjc0MSw0LjE2OCwwbDczLjc3Miw0Mi41MjdjMS4yODMsMC43NDEsMi4xODYsMi4xMDksMi4xODYsMy41OVYxNzIuODk4eicvPg0KPC9zdmc+">
|
||||
<style>
|
||||
body {
|
||||
font-family:Arial, "Helvetica Neue", Helvetica, sans-serif;
|
||||
font-size:16px;
|
||||
font-weight:normal;
|
||||
margin:0;
|
||||
padding:0;
|
||||
color:#333
|
||||
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
#overview {
|
||||
padding:20px 30px
|
||||
}
|
||||
td, th {
|
||||
padding:5px 10px
|
||||
}
|
||||
h1 {
|
||||
margin:0
|
||||
}
|
||||
table {
|
||||
margin:30px;
|
||||
width:calc(100% - 60px);
|
||||
max-width:1000px;
|
||||
border-radius:5px;
|
||||
border:1px solid #ddd;
|
||||
border-spacing:0px;
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
font-weight:400;
|
||||
font-size:medium;
|
||||
text-align:left;
|
||||
cursor:pointer
|
||||
padding: 5px 10px;
|
||||
}
|
||||
td.clr-1, td.clr-2, th span {
|
||||
font-weight:700
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
margin: 30px;
|
||||
width: calc(100% - 60px);
|
||||
max-width: 1000px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ddd;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: 400;
|
||||
font-size: medium;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
td.clr-1,
|
||||
td.clr-2,
|
||||
th span {
|
||||
float:right;
|
||||
margin-left:20px
|
||||
font-weight: 700;
|
||||
}
|
||||
th span:after {
|
||||
content:"";
|
||||
clear:both;
|
||||
display:block
|
||||
|
||||
th span {
|
||||
float: right;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
th span::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: block;
|
||||
}
|
||||
|
||||
tr:last-child td {
|
||||
border-bottom:none
|
||||
border-bottom: none;
|
||||
}
|
||||
tr td:first-child, tr td:last-child {
|
||||
color:#9da0a4
|
||||
|
||||
tr td:first-child,
|
||||
tr td:last-child {
|
||||
color: #9da0a4;
|
||||
}
|
||||
#overview.bg-0, tr.bg-0 th {
|
||||
color:#468847;
|
||||
background:#dff0d8;
|
||||
border-bottom:1px solid #d6e9c6
|
||||
|
||||
#overview.bg-0,
|
||||
tr.bg-0 th {
|
||||
color: #468847;
|
||||
background: #dff0d8;
|
||||
border-bottom: 1px solid #d6e9c6;
|
||||
}
|
||||
#overview.bg-1, tr.bg-1 th {
|
||||
color:#f0ad4e;
|
||||
background:#fcf8e3;
|
||||
border-bottom:1px solid #fbeed5
|
||||
|
||||
#overview.bg-1,
|
||||
tr.bg-1 th {
|
||||
color: #f0ad4e;
|
||||
background: #fcf8e3;
|
||||
border-bottom: 1px solid #fbeed5;
|
||||
}
|
||||
#overview.bg-2, tr.bg-2 th {
|
||||
color:#b94a48;
|
||||
background:#f2dede;
|
||||
border-bottom:1px solid #eed3d7
|
||||
|
||||
#overview.bg-2,
|
||||
tr.bg-2 th {
|
||||
color: #b94a48;
|
||||
background: #f2dede;
|
||||
border-bottom: 1px solid #eed3d7;
|
||||
}
|
||||
|
||||
td {
|
||||
border-bottom:1px solid #ddd
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
td.clr-1 {
|
||||
color:#f0ad4e
|
||||
color: #f0ad4e;
|
||||
}
|
||||
|
||||
td.clr-2 {
|
||||
color:#b94a48
|
||||
color: #b94a48;
|
||||
}
|
||||
|
||||
td a {
|
||||
color:#3a33d1;
|
||||
text-decoration:none
|
||||
color: #3a33d1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
td a:hover {
|
||||
color:#272296;
|
||||
text-decoration:underline
|
||||
color: #272296;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
|
@ -149,7 +176,7 @@ function pageTemplate(it) {
|
|||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`.trimLeft();
|
||||
`.trimStart();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -212,7 +239,7 @@ function messageTemplate(it) {
|
|||
} = it;
|
||||
|
||||
return `
|
||||
<tr style="display:none" class="f-${parentIndex}">
|
||||
<tr style="display: none;" class="f-${parentIndex}">
|
||||
<td>${lineNumber}:${columnNumber}</td>
|
||||
<td class="clr-${severityNumber}">${severityName}</td>
|
||||
<td>${encodeHTML(message)}</td>
|
||||
|
|
@ -220,7 +247,7 @@ function messageTemplate(it) {
|
|||
<a href="${ruleUrl ? ruleUrl : ""}" target="_blank" rel="noopener noreferrer">${ruleId ? ruleId : ""}</a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trimLeft();
|
||||
`.trimStart();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -278,11 +305,11 @@ function resultTemplate(it) {
|
|||
<span>${encodeHTML(summary)}</span>
|
||||
</th>
|
||||
</tr>
|
||||
`.trimLeft();
|
||||
`.trimStart();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* Render the results.
|
||||
* @param {Array} results Test results.
|
||||
* @param {Object} rulesMeta Dictionary containing metadata for each rule executed by the analysis.
|
||||
* @returns {string} HTML string describing the results.
|
||||
|
|
|
|||
159
node_modules/eslint/lib/cli-engine/formatters/table.js
generated
vendored
159
node_modules/eslint/lib/cli-engine/formatters/table.js
generated
vendored
|
|
@ -1,159 +0,0 @@
|
|||
/**
|
||||
* @fileoverview "table reporter.
|
||||
* @author Gajus Kuizinas <gajus@gajus.com>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const chalk = require("chalk"),
|
||||
table = require("table").table;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Given a word and a count, append an "s" if count is not one.
|
||||
* @param {string} word A word.
|
||||
* @param {number} count Quantity.
|
||||
* @returns {string} The original word with an s on the end if count is not one.
|
||||
*/
|
||||
function pluralize(word, count) {
|
||||
return (count === 1 ? word : `${word}s`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws text table.
|
||||
* @param {Array<Object>} messages Error messages relating to a specific file.
|
||||
* @returns {string} A text table.
|
||||
*/
|
||||
function drawTable(messages) {
|
||||
const rows = [];
|
||||
|
||||
if (messages.length === 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
rows.push([
|
||||
chalk.bold("Line"),
|
||||
chalk.bold("Column"),
|
||||
chalk.bold("Type"),
|
||||
chalk.bold("Message"),
|
||||
chalk.bold("Rule ID")
|
||||
]);
|
||||
|
||||
messages.forEach(message => {
|
||||
let messageType;
|
||||
|
||||
if (message.fatal || message.severity === 2) {
|
||||
messageType = chalk.red("error");
|
||||
} else {
|
||||
messageType = chalk.yellow("warning");
|
||||
}
|
||||
|
||||
rows.push([
|
||||
message.line || 0,
|
||||
message.column || 0,
|
||||
messageType,
|
||||
message.message,
|
||||
message.ruleId || ""
|
||||
]);
|
||||
});
|
||||
|
||||
return table(rows, {
|
||||
columns: {
|
||||
0: {
|
||||
width: 8,
|
||||
wrapWord: true
|
||||
},
|
||||
1: {
|
||||
width: 8,
|
||||
wrapWord: true
|
||||
},
|
||||
2: {
|
||||
width: 8,
|
||||
wrapWord: true
|
||||
},
|
||||
3: {
|
||||
paddingRight: 5,
|
||||
width: 50,
|
||||
wrapWord: true
|
||||
},
|
||||
4: {
|
||||
width: 20,
|
||||
wrapWord: true
|
||||
}
|
||||
},
|
||||
drawHorizontalLine(index) {
|
||||
return index === 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a report (multiple tables).
|
||||
* @param {Array} results Report results for every file.
|
||||
* @returns {string} A column of text tables.
|
||||
*/
|
||||
function drawReport(results) {
|
||||
let files;
|
||||
|
||||
files = results.map(result => {
|
||||
if (!result.messages.length) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return `\n${result.filePath}\n\n${drawTable(result.messages)}`;
|
||||
});
|
||||
|
||||
files = files.filter(content => content.trim());
|
||||
|
||||
return files.join("");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = function(report) {
|
||||
let result,
|
||||
errorCount,
|
||||
warningCount;
|
||||
|
||||
result = "";
|
||||
errorCount = 0;
|
||||
warningCount = 0;
|
||||
|
||||
report.forEach(fileReport => {
|
||||
errorCount += fileReport.errorCount;
|
||||
warningCount += fileReport.warningCount;
|
||||
});
|
||||
|
||||
if (errorCount || warningCount) {
|
||||
result = drawReport(report);
|
||||
}
|
||||
|
||||
result += `\n${table([
|
||||
[
|
||||
chalk.red(pluralize(`${errorCount} Error`, errorCount))
|
||||
],
|
||||
[
|
||||
chalk.yellow(pluralize(`${warningCount} Warning`, warningCount))
|
||||
]
|
||||
], {
|
||||
columns: {
|
||||
0: {
|
||||
width: 110,
|
||||
wrapWord: true
|
||||
}
|
||||
},
|
||||
drawHorizontalLine() {
|
||||
return true;
|
||||
}
|
||||
})}`;
|
||||
|
||||
return result;
|
||||
};
|
||||
2
node_modules/eslint/lib/cli-engine/formatters/tap.js
generated
vendored
2
node_modules/eslint/lib/cli-engine/formatters/tap.js
generated
vendored
|
|
@ -31,7 +31,7 @@ function outputDiagnostics(diagnostic) {
|
|||
const prefix = " ";
|
||||
let output = `${prefix}---\n`;
|
||||
|
||||
output += prefix + yaml.safeDump(diagnostic).split("\n").join(`\n${prefix}`);
|
||||
output += prefix + yaml.dump(diagnostic).split("\n").join(`\n${prefix}`);
|
||||
output += "...\n";
|
||||
return output;
|
||||
}
|
||||
|
|
|
|||
4
node_modules/eslint/lib/cli-engine/hash.js
generated
vendored
4
node_modules/eslint/lib/cli-engine/hash.js
generated
vendored
|
|
@ -21,8 +21,8 @@ const murmur = require("imurmurhash");
|
|||
|
||||
/**
|
||||
* hash the given string
|
||||
* @param {string} str the string to hash
|
||||
* @returns {string} the hash
|
||||
* @param {string} str the string to hash
|
||||
* @returns {string} the hash
|
||||
*/
|
||||
function hash(str) {
|
||||
return murmur(str).result().toString(36);
|
||||
|
|
|
|||
2
node_modules/eslint/lib/cli-engine/lint-result-cache.js
generated
vendored
2
node_modules/eslint/lib/cli-engine/lint-result-cache.js
generated
vendored
|
|
@ -36,7 +36,7 @@ const invalidCacheStrategyErrorMessage = `Cache strategy must be one of: ${valid
|
|||
*/
|
||||
function isValidCacheStrategy(cacheStrategy) {
|
||||
return (
|
||||
validCacheStrategies.indexOf(cacheStrategy) !== -1
|
||||
validCacheStrategies.includes(cacheStrategy)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
2
node_modules/eslint/lib/cli-engine/xml-escape.js
generated
vendored
2
node_modules/eslint/lib/cli-engine/xml-escape.js
generated
vendored
|
|
@ -15,7 +15,7 @@
|
|||
* @private
|
||||
*/
|
||||
module.exports = function(s) {
|
||||
return (`${s}`).replace(/[<>&"'\x00-\x1F\x7F\u0080-\uFFFF]/gu, c => { // eslint-disable-line no-control-regex
|
||||
return (`${s}`).replace(/[<>&"'\x00-\x1F\x7F\u0080-\uFFFF]/gu, c => { // eslint-disable-line no-control-regex -- Converting controls to entities
|
||||
switch (c) {
|
||||
case "<":
|
||||
return "<";
|
||||
|
|
|
|||
203
node_modules/eslint/lib/cli.js
generated
vendored
203
node_modules/eslint/lib/cli.js
generated
vendored
|
|
@ -6,7 +6,7 @@
|
|||
"use strict";
|
||||
|
||||
/*
|
||||
* The CLI object should *not* call process.exit() directly. It should only return
|
||||
* NOTE: The CLI object should *not* call process.exit() directly. It should only return
|
||||
* exit codes. This allows other programs to use the CLI object and still control
|
||||
* when the program exits.
|
||||
*/
|
||||
|
|
@ -19,9 +19,13 @@ const fs = require("fs"),
|
|||
path = require("path"),
|
||||
{ promisify } = require("util"),
|
||||
{ ESLint } = require("./eslint"),
|
||||
CLIOptions = require("./options"),
|
||||
{ FlatESLint } = require("./eslint/flat-eslint"),
|
||||
createCLIOptions = require("./options"),
|
||||
log = require("./shared/logging"),
|
||||
RuntimeInfo = require("./shared/runtime-info");
|
||||
const { Legacy: { naming } } = require("@eslint/eslintrc");
|
||||
const { findFlatConfigFile } = require("./eslint/flat-eslint");
|
||||
const { ModuleImporter } = require("@humanwhocodes/module-importer");
|
||||
|
||||
const debug = require("debug")("eslint:cli");
|
||||
|
||||
|
|
@ -33,6 +37,7 @@ const debug = require("debug")("eslint:cli");
|
|||
/** @typedef {import("./eslint/eslint").LintMessage} LintMessage */
|
||||
/** @typedef {import("./eslint/eslint").LintResult} LintResult */
|
||||
/** @typedef {import("./options").ParsedCLIOptions} ParsedCLIOptions */
|
||||
/** @typedef {import("./shared/types").ResultsMeta} ResultsMeta */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
|
@ -54,17 +59,20 @@ function quietFixPredicate(message) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Translates the CLI options into the options expected by the CLIEngine.
|
||||
* Translates the CLI options into the options expected by the ESLint constructor.
|
||||
* @param {ParsedCLIOptions} cliOptions The CLI options to translate.
|
||||
* @returns {ESLintOptions} The options object for the CLIEngine.
|
||||
* @param {"flat"|"eslintrc"} [configType="eslintrc"] The format of the
|
||||
* config to generate.
|
||||
* @returns {Promise<ESLintOptions>} The options object for the ESLint constructor.
|
||||
* @private
|
||||
*/
|
||||
function translateOptions({
|
||||
async function translateOptions({
|
||||
cache,
|
||||
cacheFile,
|
||||
cacheLocation,
|
||||
cacheStrategy,
|
||||
config,
|
||||
configLookup,
|
||||
env,
|
||||
errorOnUnmatchedPattern,
|
||||
eslintrc,
|
||||
|
|
@ -85,19 +93,60 @@ function translateOptions({
|
|||
resolvePluginsRelativeTo,
|
||||
rule,
|
||||
rulesdir
|
||||
}) {
|
||||
return {
|
||||
allowInlineConfig: inlineConfig,
|
||||
cache,
|
||||
cacheLocation: cacheLocation || cacheFile,
|
||||
cacheStrategy,
|
||||
errorOnUnmatchedPattern,
|
||||
extensions: ext,
|
||||
fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
|
||||
fixTypes: fixType,
|
||||
ignore,
|
||||
ignorePath,
|
||||
overrideConfig: {
|
||||
}, configType) {
|
||||
|
||||
let overrideConfig, overrideConfigFile;
|
||||
const importer = new ModuleImporter();
|
||||
|
||||
if (configType === "flat") {
|
||||
overrideConfigFile = (typeof config === "string") ? config : !configLookup;
|
||||
if (overrideConfigFile === false) {
|
||||
overrideConfigFile = void 0;
|
||||
}
|
||||
|
||||
let globals = {};
|
||||
|
||||
if (global) {
|
||||
globals = global.reduce((obj, name) => {
|
||||
if (name.endsWith(":true")) {
|
||||
obj[name.slice(0, -5)] = "writable";
|
||||
} else {
|
||||
obj[name] = "readonly";
|
||||
}
|
||||
return obj;
|
||||
}, globals);
|
||||
}
|
||||
|
||||
overrideConfig = [{
|
||||
languageOptions: {
|
||||
globals,
|
||||
parserOptions: parserOptions || {}
|
||||
},
|
||||
rules: rule ? rule : {}
|
||||
}];
|
||||
|
||||
if (parser) {
|
||||
overrideConfig[0].languageOptions.parser = await importer.import(parser);
|
||||
}
|
||||
|
||||
if (plugin) {
|
||||
const plugins = {};
|
||||
|
||||
for (const pluginName of plugin) {
|
||||
|
||||
const shortName = naming.getShorthandName(pluginName, "eslint-plugin");
|
||||
const longName = naming.normalizePackageName(pluginName, "eslint-plugin");
|
||||
|
||||
plugins[shortName] = await importer.import(longName);
|
||||
}
|
||||
|
||||
overrideConfig[0].plugins = plugins;
|
||||
}
|
||||
|
||||
} else {
|
||||
overrideConfigFile = config;
|
||||
|
||||
overrideConfig = {
|
||||
env: env && env.reduce((obj, name) => {
|
||||
obj[name] = true;
|
||||
return obj;
|
||||
|
|
@ -115,19 +164,40 @@ function translateOptions({
|
|||
parserOptions,
|
||||
plugins: plugin,
|
||||
rules: rule
|
||||
},
|
||||
overrideConfigFile: config,
|
||||
reportUnusedDisableDirectives: reportUnusedDisableDirectives ? "error" : void 0,
|
||||
resolvePluginsRelativeTo,
|
||||
rulePaths: rulesdir,
|
||||
useEslintrc: eslintrc
|
||||
};
|
||||
}
|
||||
|
||||
const options = {
|
||||
allowInlineConfig: inlineConfig,
|
||||
cache,
|
||||
cacheLocation: cacheLocation || cacheFile,
|
||||
cacheStrategy,
|
||||
errorOnUnmatchedPattern,
|
||||
fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
|
||||
fixTypes: fixType,
|
||||
ignore,
|
||||
overrideConfig,
|
||||
overrideConfigFile,
|
||||
reportUnusedDisableDirectives: reportUnusedDisableDirectives ? "error" : void 0
|
||||
};
|
||||
|
||||
if (configType === "flat") {
|
||||
options.ignorePatterns = ignorePattern;
|
||||
} else {
|
||||
options.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
|
||||
options.rulePaths = rulesdir;
|
||||
options.useEslintrc = eslintrc;
|
||||
options.extensions = ext;
|
||||
options.ignorePath = ignorePath;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count error messages.
|
||||
* @param {LintResult[]} results The lint results.
|
||||
* @returns {{errorCount:number;warningCount:number}} The number of error messages.
|
||||
* @returns {{errorCount:number;fatalErrorCount:number,warningCount:number}} The number of error messages.
|
||||
*/
|
||||
function countErrors(results) {
|
||||
let errorCount = 0;
|
||||
|
|
@ -165,10 +235,11 @@ async function isDirectory(filePath) {
|
|||
* @param {LintResult[]} results The results to print.
|
||||
* @param {string} format The name of the formatter to use or the path to the formatter.
|
||||
* @param {string} outputFile The path for the output file.
|
||||
* @param {ResultsMeta} resultsMeta Warning count and max threshold.
|
||||
* @returns {Promise<boolean>} True if the printing succeeds, false if not.
|
||||
* @private
|
||||
*/
|
||||
async function printResults(engine, results, format, outputFile) {
|
||||
async function printResults(engine, results, format, outputFile, resultsMeta) {
|
||||
let formatter;
|
||||
|
||||
try {
|
||||
|
|
@ -178,7 +249,7 @@ async function printResults(engine, results, format, outputFile) {
|
|||
return false;
|
||||
}
|
||||
|
||||
const output = formatter.format(results);
|
||||
const output = await formatter.format(results, resultsMeta);
|
||||
|
||||
if (output) {
|
||||
if (outputFile) {
|
||||
|
|
@ -204,6 +275,31 @@ async function printResults(engine, results, format, outputFile) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether flat config should be used.
|
||||
* @param {boolean} [allowFlatConfig] Whether or not to allow flat config.
|
||||
* @returns {Promise<boolean>} Where flat config should be used.
|
||||
*/
|
||||
async function shouldUseFlatConfig(allowFlatConfig) {
|
||||
if (!allowFlatConfig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (process.env.ESLINT_USE_FLAT_CONFIG) {
|
||||
case "true":
|
||||
return true;
|
||||
case "false":
|
||||
return false;
|
||||
default:
|
||||
|
||||
/*
|
||||
* If neither explicitly enabled nor disabled, then use the presence
|
||||
* of a flat config file to determine enablement.
|
||||
*/
|
||||
return !!(await findFlatConfigFile(process.cwd()));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -218,19 +314,34 @@ const cli = {
|
|||
* Executes the CLI based on an array of arguments that is passed in.
|
||||
* @param {string|Array|Object} args The arguments to process.
|
||||
* @param {string} [text] The text to lint (used for TTY).
|
||||
* @param {boolean} [allowFlatConfig] Whether or not to allow flat config.
|
||||
* @returns {Promise<number>} The exit code for the operation.
|
||||
*/
|
||||
async execute(args, text) {
|
||||
async execute(args, text, allowFlatConfig) {
|
||||
if (Array.isArray(args)) {
|
||||
debug("CLI args: %o", args.slice(2));
|
||||
}
|
||||
|
||||
/*
|
||||
* Before doing anything, we need to see if we are using a
|
||||
* flat config file. If so, then we need to change the way command
|
||||
* line args are parsed. This is temporary, and when we fully
|
||||
* switch to flat config we can remove this logic.
|
||||
*/
|
||||
|
||||
const usingFlatConfig = await shouldUseFlatConfig(allowFlatConfig);
|
||||
|
||||
debug("Using flat config?", usingFlatConfig);
|
||||
|
||||
const CLIOptions = createCLIOptions(usingFlatConfig);
|
||||
|
||||
/** @type {ParsedCLIOptions} */
|
||||
let options;
|
||||
|
||||
try {
|
||||
options = CLIOptions.parse(args);
|
||||
} catch (error) {
|
||||
debug("Error parsing CLI options:", error.message);
|
||||
log.error(error.message);
|
||||
return 2;
|
||||
}
|
||||
|
|
@ -251,6 +362,7 @@ const cli = {
|
|||
log.info(RuntimeInfo.environment());
|
||||
return 0;
|
||||
} catch (err) {
|
||||
debug("Error retrieving environment info");
|
||||
log.error(err.message);
|
||||
return 2;
|
||||
}
|
||||
|
|
@ -266,7 +378,9 @@ const cli = {
|
|||
return 2;
|
||||
}
|
||||
|
||||
const engine = new ESLint(translateOptions(options));
|
||||
const engine = usingFlatConfig
|
||||
? new FlatESLint(await translateOptions(options, "flat"))
|
||||
: new ESLint(await translateOptions(options));
|
||||
const fileConfig =
|
||||
await engine.calculateConfigForFile(options.printConfig);
|
||||
|
||||
|
|
@ -289,7 +403,9 @@ const cli = {
|
|||
return 2;
|
||||
}
|
||||
|
||||
const engine = new ESLint(translateOptions(options));
|
||||
const ActiveESLint = usingFlatConfig ? FlatESLint : ESLint;
|
||||
|
||||
const engine = new ActiveESLint(await translateOptions(options, usingFlatConfig ? "flat" : "eslintrc"));
|
||||
let results;
|
||||
|
||||
if (useStdin) {
|
||||
|
|
@ -303,27 +419,34 @@ const cli = {
|
|||
|
||||
if (options.fix) {
|
||||
debug("Fix mode enabled - applying fixes");
|
||||
await ESLint.outputFixes(results);
|
||||
await ActiveESLint.outputFixes(results);
|
||||
}
|
||||
|
||||
let resultsToPrint = results;
|
||||
|
||||
if (options.quiet) {
|
||||
debug("Quiet mode enabled - filtering out warnings");
|
||||
resultsToPrint = ESLint.getErrorResults(resultsToPrint);
|
||||
resultsToPrint = ActiveESLint.getErrorResults(resultsToPrint);
|
||||
}
|
||||
|
||||
if (await printResults(engine, resultsToPrint, options.format, options.outputFile)) {
|
||||
const resultCounts = countErrors(results);
|
||||
const tooManyWarnings = options.maxWarnings >= 0 && resultCounts.warningCount > options.maxWarnings;
|
||||
const resultsMeta = tooManyWarnings
|
||||
? {
|
||||
maxWarningsExceeded: {
|
||||
maxWarnings: options.maxWarnings,
|
||||
foundWarnings: resultCounts.warningCount
|
||||
}
|
||||
}
|
||||
: {};
|
||||
|
||||
if (await printResults(engine, resultsToPrint, options.format, options.outputFile, resultsMeta)) {
|
||||
|
||||
// Errors and warnings from the original unfiltered results should determine the exit code
|
||||
const { errorCount, fatalErrorCount, warningCount } = countErrors(results);
|
||||
|
||||
const tooManyWarnings =
|
||||
options.maxWarnings >= 0 && warningCount > options.maxWarnings;
|
||||
const shouldExitForFatalErrors =
|
||||
options.exitOnFatalError && fatalErrorCount > 0;
|
||||
options.exitOnFatalError && resultCounts.fatalErrorCount > 0;
|
||||
|
||||
if (!errorCount && tooManyWarnings) {
|
||||
if (!resultCounts.errorCount && tooManyWarnings) {
|
||||
log.error(
|
||||
"ESLint found too many warnings (maximum: %s).",
|
||||
options.maxWarnings
|
||||
|
|
@ -334,7 +457,7 @@ const cli = {
|
|||
return 2;
|
||||
}
|
||||
|
||||
return (errorCount || tooManyWarnings) ? 1 : 0;
|
||||
return (resultCounts.errorCount || tooManyWarnings) ? 1 : 0;
|
||||
}
|
||||
|
||||
return 2;
|
||||
|
|
|
|||
32
node_modules/eslint/lib/config/default-config.js
generated
vendored
32
node_modules/eslint/lib/config/default-config.js
generated
vendored
|
|
@ -15,7 +15,6 @@ const Rules = require("../rules");
|
|||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
exports.defaultConfig = [
|
||||
{
|
||||
plugins: {
|
||||
|
|
@ -26,7 +25,7 @@ exports.defaultConfig = [
|
|||
|
||||
/*
|
||||
* Because we try to delay loading rules until absolutely
|
||||
* necessary, a proxy allows us to hook into the lazy-loading
|
||||
* necessary, a proxy allows us to hook into the lazy-loading
|
||||
* aspect of the rules map while still keeping all of the
|
||||
* relevant configuration inside of the config array.
|
||||
*/
|
||||
|
|
@ -41,12 +40,31 @@ exports.defaultConfig = [
|
|||
})
|
||||
}
|
||||
},
|
||||
ignores: [
|
||||
"**/node_modules/**",
|
||||
".git/**"
|
||||
],
|
||||
languageOptions: {
|
||||
parser: "@/espree"
|
||||
sourceType: "module",
|
||||
ecmaVersion: "latest",
|
||||
parser: "@/espree",
|
||||
parserOptions: {}
|
||||
}
|
||||
},
|
||||
|
||||
// default ignores are listed here
|
||||
{
|
||||
ignores: [
|
||||
"**/node_modules/*",
|
||||
".git/"
|
||||
]
|
||||
},
|
||||
|
||||
// intentionally empty config to ensure these files are globbed by default
|
||||
{
|
||||
files: ["**/*.js", "**/*.mjs"]
|
||||
},
|
||||
{
|
||||
files: ["**/*.cjs"],
|
||||
languageOptions: {
|
||||
sourceType: "commonjs",
|
||||
ecmaVersion: "latest"
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
|
|||
127
node_modules/eslint/lib/config/flat-config-array.js
generated
vendored
127
node_modules/eslint/lib/config/flat-config-array.js
generated
vendored
|
|
@ -14,7 +14,6 @@ const { flatConfigSchema } = require("./flat-config-schema");
|
|||
const { RuleValidator } = require("./rule-validator");
|
||||
const { defaultConfig } = require("./default-config");
|
||||
const recommendedConfig = require("../../conf/eslint-recommended");
|
||||
const allConfig = require("../../conf/eslint-all");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
|
@ -37,6 +36,8 @@ function splitPluginIdentifier(identifier) {
|
|||
};
|
||||
}
|
||||
|
||||
const originalBaseConfig = Symbol("originalBaseConfig");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -49,19 +50,43 @@ class FlatConfigArray extends ConfigArray {
|
|||
/**
|
||||
* Creates a new instance.
|
||||
* @param {*[]} configs An array of configuration information.
|
||||
* @param {{basePath: string, baseConfig: FlatConfig}} options The options
|
||||
* @param {{basePath: string, shouldIgnore: boolean, baseConfig: FlatConfig}} options The options
|
||||
* to use for the config array instance.
|
||||
*/
|
||||
constructor(configs, { basePath, baseConfig = defaultConfig }) {
|
||||
constructor(configs, {
|
||||
basePath,
|
||||
shouldIgnore = true,
|
||||
baseConfig = defaultConfig
|
||||
} = {}) {
|
||||
super(configs, {
|
||||
basePath,
|
||||
schema: flatConfigSchema
|
||||
});
|
||||
|
||||
this.unshift(baseConfig);
|
||||
if (baseConfig[Symbol.iterator]) {
|
||||
this.unshift(...baseConfig);
|
||||
} else {
|
||||
this.unshift(baseConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* The base config used to build the config array.
|
||||
* @type {Array<FlatConfig>}
|
||||
*/
|
||||
this[originalBaseConfig] = baseConfig;
|
||||
Object.defineProperty(this, originalBaseConfig, { writable: false });
|
||||
|
||||
/**
|
||||
* Determines if `ignores` fields should be honored.
|
||||
* If true, then all `ignores` fields are honored.
|
||||
* if false, then only `ignores` fields in the baseConfig are honored.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.shouldIgnore = shouldIgnore;
|
||||
Object.defineProperty(this, "shouldIgnore", { writable: false });
|
||||
}
|
||||
|
||||
/* eslint-disable class-methods-use-this */
|
||||
/* eslint-disable class-methods-use-this -- Desired as instance method */
|
||||
/**
|
||||
* Replaces a config with another config to allow us to put strings
|
||||
* in the config array that will be replaced by objects before
|
||||
|
|
@ -75,7 +100,30 @@ class FlatConfigArray extends ConfigArray {
|
|||
}
|
||||
|
||||
if (config === "eslint:all") {
|
||||
return allConfig;
|
||||
|
||||
/*
|
||||
* Load `eslint-all.js` here instead of at the top level to avoid loading all rule modules
|
||||
* when it isn't necessary. `eslint-all.js` reads `meta` of rule objects to filter out deprecated ones,
|
||||
* so requiring `eslint-all.js` module loads all rule modules as a consequence.
|
||||
*/
|
||||
return require("../../conf/eslint-all");
|
||||
}
|
||||
|
||||
/*
|
||||
* If `shouldIgnore` is false, we remove any ignore patterns specified
|
||||
* in the config so long as it's not a default config and it doesn't
|
||||
* have a `files` entry.
|
||||
*/
|
||||
if (
|
||||
!this.shouldIgnore &&
|
||||
!this[originalBaseConfig].includes(config) &&
|
||||
config.ignores &&
|
||||
!config.files
|
||||
) {
|
||||
/* eslint-disable-next-line no-unused-vars -- need to strip off other keys */
|
||||
const { ignores, ...otherKeys } = config;
|
||||
|
||||
return otherKeys;
|
||||
}
|
||||
|
||||
return config;
|
||||
|
|
@ -91,34 +139,75 @@ class FlatConfigArray extends ConfigArray {
|
|||
[ConfigArraySymbol.finalizeConfig](config) {
|
||||
|
||||
const { plugins, languageOptions, processor } = config;
|
||||
let parserName, processorName;
|
||||
let invalidParser = false,
|
||||
invalidProcessor = false;
|
||||
|
||||
// Check parser value
|
||||
if (languageOptions && languageOptions.parser && typeof languageOptions.parser === "string") {
|
||||
const { pluginName, objectName: parserName } = splitPluginIdentifier(languageOptions.parser);
|
||||
if (languageOptions && languageOptions.parser) {
|
||||
if (typeof languageOptions.parser === "string") {
|
||||
const { pluginName, objectName: localParserName } = splitPluginIdentifier(languageOptions.parser);
|
||||
|
||||
if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[parserName]) {
|
||||
throw new TypeError(`Key "parser": Could not find "${parserName}" in plugin "${pluginName}".`);
|
||||
parserName = languageOptions.parser;
|
||||
|
||||
if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[localParserName]) {
|
||||
throw new TypeError(`Key "parser": Could not find "${localParserName}" in plugin "${pluginName}".`);
|
||||
}
|
||||
|
||||
languageOptions.parser = plugins[pluginName].parsers[localParserName];
|
||||
} else {
|
||||
invalidParser = true;
|
||||
}
|
||||
|
||||
languageOptions.parser = plugins[pluginName].parsers[parserName];
|
||||
}
|
||||
|
||||
// Check processor value
|
||||
if (processor && typeof processor === "string") {
|
||||
const { pluginName, objectName: processorName } = splitPluginIdentifier(processor);
|
||||
if (processor) {
|
||||
if (typeof processor === "string") {
|
||||
const { pluginName, objectName: localProcessorName } = splitPluginIdentifier(processor);
|
||||
|
||||
if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[processorName]) {
|
||||
throw new TypeError(`Key "processor": Could not find "${processorName}" in plugin "${pluginName}".`);
|
||||
processorName = processor;
|
||||
|
||||
if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[localProcessorName]) {
|
||||
throw new TypeError(`Key "processor": Could not find "${localProcessorName}" in plugin "${pluginName}".`);
|
||||
}
|
||||
|
||||
config.processor = plugins[pluginName].processors[localProcessorName];
|
||||
} else {
|
||||
invalidProcessor = true;
|
||||
}
|
||||
|
||||
config.processor = plugins[pluginName].processors[processorName];
|
||||
}
|
||||
|
||||
ruleValidator.validate(config);
|
||||
|
||||
// apply special logic for serialization into JSON
|
||||
/* eslint-disable object-shorthand -- shorthand would change "this" value */
|
||||
Object.defineProperty(config, "toJSON", {
|
||||
value: function() {
|
||||
|
||||
if (invalidParser) {
|
||||
throw new Error("Caching is not supported when parser is an object.");
|
||||
}
|
||||
|
||||
if (invalidProcessor) {
|
||||
throw new Error("Caching is not supported when processor is an object.");
|
||||
}
|
||||
|
||||
return {
|
||||
...this,
|
||||
plugins: Object.keys(plugins),
|
||||
languageOptions: {
|
||||
...languageOptions,
|
||||
parser: parserName
|
||||
},
|
||||
processor: processorName
|
||||
};
|
||||
}
|
||||
});
|
||||
/* eslint-enable object-shorthand -- ok to enable now */
|
||||
|
||||
return config;
|
||||
}
|
||||
/* eslint-enable class-methods-use-this */
|
||||
/* eslint-enable class-methods-use-this -- Desired as instance method */
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
111
node_modules/eslint/lib/config/flat-config-helpers.js
generated
vendored
Normal file
111
node_modules/eslint/lib/config/flat-config-helpers.js
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* @fileoverview Shared functions to work with configs.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parses a ruleId into its plugin and rule parts.
|
||||
* @param {string} ruleId The rule ID to parse.
|
||||
* @returns {{pluginName:string,ruleName:string}} The plugin and rule
|
||||
* parts of the ruleId;
|
||||
*/
|
||||
function parseRuleId(ruleId) {
|
||||
let pluginName, ruleName;
|
||||
|
||||
// distinguish between core rules and plugin rules
|
||||
if (ruleId.includes("/")) {
|
||||
|
||||
// mimic scoped npm packages
|
||||
if (ruleId.startsWith("@")) {
|
||||
pluginName = ruleId.slice(0, ruleId.lastIndexOf("/"));
|
||||
} else {
|
||||
pluginName = ruleId.slice(0, ruleId.indexOf("/"));
|
||||
}
|
||||
|
||||
ruleName = ruleId.slice(pluginName.length + 1);
|
||||
} else {
|
||||
pluginName = "@";
|
||||
ruleName = ruleId;
|
||||
}
|
||||
|
||||
return {
|
||||
pluginName,
|
||||
ruleName
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a rule instance from a given config based on the ruleId.
|
||||
* @param {string} ruleId The rule ID to look for.
|
||||
* @param {FlatConfig} config The config to search.
|
||||
* @returns {import("../shared/types").Rule|undefined} The rule if found
|
||||
* or undefined if not.
|
||||
*/
|
||||
function getRuleFromConfig(ruleId, config) {
|
||||
|
||||
const { pluginName, ruleName } = parseRuleId(ruleId);
|
||||
|
||||
const plugin = config.plugins && config.plugins[pluginName];
|
||||
let rule = plugin && plugin.rules && plugin.rules[ruleName];
|
||||
|
||||
|
||||
// normalize function rules into objects
|
||||
if (rule && typeof rule === "function") {
|
||||
rule = {
|
||||
create: rule
|
||||
};
|
||||
}
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a complete options schema for a rule.
|
||||
* @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
|
||||
* @returns {Object} JSON Schema for the rule's options.
|
||||
*/
|
||||
function getRuleOptionsSchema(rule) {
|
||||
|
||||
if (!rule) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const schema = rule.schema || rule.meta && rule.meta.schema;
|
||||
|
||||
if (Array.isArray(schema)) {
|
||||
if (schema.length) {
|
||||
return {
|
||||
type: "array",
|
||||
items: schema,
|
||||
minItems: 0,
|
||||
maxItems: schema.length
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: "array",
|
||||
minItems: 0,
|
||||
maxItems: 0
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Given a full schema, leave it alone
|
||||
return schema || null;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
parseRuleId,
|
||||
getRuleFromConfig,
|
||||
getRuleOptionsSchema
|
||||
};
|
||||
23
node_modules/eslint/lib/config/flat-config-schema.js
generated
vendored
23
node_modules/eslint/lib/config/flat-config-schema.js
generated
vendored
|
|
@ -195,13 +195,6 @@ function assertIsObjectOrString(value) {
|
|||
// Low-Level Schemas
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const numberSchema = {
|
||||
merge: "replace",
|
||||
validate: "number"
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const booleanSchema = {
|
||||
merge: "replace",
|
||||
|
|
@ -336,7 +329,7 @@ const rulesSchema = {
|
|||
// avoid hairy edge case
|
||||
if (ruleId === "__proto__") {
|
||||
|
||||
/* eslint-disable-next-line no-proto */
|
||||
/* eslint-disable-next-line no-proto -- Though deprecated, may still be present */
|
||||
delete result.__proto__;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -415,6 +408,18 @@ const rulesSchema = {
|
|||
}
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const ecmaVersionSchema = {
|
||||
merge: "replace",
|
||||
validate(value) {
|
||||
if (typeof value === "number" || value === "latest") {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new TypeError("Expected a number or \"latest\".");
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const sourceTypeSchema = {
|
||||
merge: "replace",
|
||||
|
|
@ -439,7 +444,7 @@ exports.flatConfigSchema = {
|
|||
},
|
||||
languageOptions: {
|
||||
schema: {
|
||||
ecmaVersion: numberSchema,
|
||||
ecmaVersion: ecmaVersionSchema,
|
||||
sourceType: sourceTypeSchema,
|
||||
globals: globalsSchema,
|
||||
parser: parserSchema,
|
||||
|
|
|
|||
86
node_modules/eslint/lib/config/rule-validator.js
generated
vendored
86
node_modules/eslint/lib/config/rule-validator.js
generated
vendored
|
|
@ -10,74 +10,59 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
const ajv = require("../shared/ajv")();
|
||||
const {
|
||||
parseRuleId,
|
||||
getRuleFromConfig,
|
||||
getRuleOptionsSchema
|
||||
} = require("./flat-config-helpers");
|
||||
const ruleReplacements = require("../../conf/replacements.json");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Finds a rule with the given ID in the given config.
|
||||
* @param {string} ruleId The ID of the rule to find.
|
||||
* Throws a helpful error when a rule cannot be found.
|
||||
* @param {Object} ruleId The rule identifier.
|
||||
* @param {string} ruleId.pluginName The ID of the rule to find.
|
||||
* @param {string} ruleId.ruleName The ID of the rule to find.
|
||||
* @param {Object} config The config to search in.
|
||||
* @returns {{create: Function, schema: (Array|null)}} THe rule object.
|
||||
* @throws {TypeError} For missing plugin or rule.
|
||||
* @returns {void}
|
||||
*/
|
||||
function findRuleDefinition(ruleId, config) {
|
||||
const ruleIdParts = ruleId.split("/");
|
||||
let pluginName, ruleName;
|
||||
function throwRuleNotFoundError({ pluginName, ruleName }, config) {
|
||||
|
||||
// built-in rule
|
||||
if (ruleIdParts.length === 1) {
|
||||
pluginName = "@";
|
||||
ruleName = ruleIdParts[0];
|
||||
} else {
|
||||
ruleName = ruleIdParts.pop();
|
||||
pluginName = ruleIdParts.join("/");
|
||||
}
|
||||
const ruleId = pluginName === "@" ? ruleName : `${pluginName}/${ruleName}`;
|
||||
|
||||
if (!config.plugins || !config.plugins[pluginName]) {
|
||||
throw new TypeError(`Key "rules": Key "${ruleId}": Could not find plugin "${pluginName}".`);
|
||||
}
|
||||
const errorMessageHeader = `Key "rules": Key "${ruleId}"`;
|
||||
let errorMessage = `${errorMessageHeader}: Could not find plugin "${pluginName}".`;
|
||||
|
||||
if (!config.plugins[pluginName].rules || !config.plugins[pluginName].rules[ruleName]) {
|
||||
throw new TypeError(`Key "rules": Key "${ruleId}": Could not find "${ruleName}" in plugin "${pluginName}".`);
|
||||
}
|
||||
// if the plugin exists then we need to check if the rule exists
|
||||
if (config.plugins && config.plugins[pluginName]) {
|
||||
const replacementRuleName = ruleReplacements.rules[ruleName];
|
||||
|
||||
return config.plugins[pluginName].rules[ruleName];
|
||||
if (pluginName === "@" && replacementRuleName) {
|
||||
|
||||
}
|
||||
errorMessage = `${errorMessageHeader}: Rule "${ruleName}" was removed and replaced by "${replacementRuleName}".`;
|
||||
|
||||
/**
|
||||
* Gets a complete options schema for a rule.
|
||||
* @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
|
||||
* @returns {Object} JSON Schema for the rule's options.
|
||||
*/
|
||||
function getRuleOptionsSchema(rule) {
|
||||
} else {
|
||||
|
||||
if (!rule) {
|
||||
return null;
|
||||
}
|
||||
errorMessage = `${errorMessageHeader}: Could not find "${ruleName}" in plugin "${pluginName}".`;
|
||||
|
||||
const schema = rule.schema || rule.meta && rule.meta.schema;
|
||||
// otherwise, let's see if we can find the rule name elsewhere
|
||||
for (const [otherPluginName, otherPlugin] of Object.entries(config.plugins)) {
|
||||
if (otherPlugin.rules && otherPlugin.rules[ruleName]) {
|
||||
errorMessage += ` Did you mean "${otherPluginName}/${ruleName}"?`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(schema)) {
|
||||
if (schema.length) {
|
||||
return {
|
||||
type: "array",
|
||||
items: schema,
|
||||
minItems: 0,
|
||||
maxItems: schema.length
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: "array",
|
||||
minItems: 0,
|
||||
maxItems: 0
|
||||
};
|
||||
|
||||
// falls through to throw error
|
||||
}
|
||||
|
||||
// Given a full schema, leave it alone
|
||||
return schema || null;
|
||||
throw new TypeError(errorMessage);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -98,7 +83,6 @@ class RuleValidator {
|
|||
* A collection of compiled validators for rules that have already
|
||||
* been validated.
|
||||
* @type {WeakMap}
|
||||
* @property validators
|
||||
*/
|
||||
this.validators = new WeakMap();
|
||||
}
|
||||
|
|
@ -137,7 +121,11 @@ class RuleValidator {
|
|||
continue;
|
||||
}
|
||||
|
||||
const rule = findRuleDefinition(ruleId, config);
|
||||
const rule = getRuleFromConfig(ruleId, config);
|
||||
|
||||
if (!rule) {
|
||||
throwRuleNotFoundError(parseRuleId(ruleId), config);
|
||||
}
|
||||
|
||||
// Precompile and cache validator the first time
|
||||
if (!this.validators.has(rule)) {
|
||||
|
|
|
|||
940
node_modules/eslint/lib/eslint/eslint-helpers.js
generated
vendored
Normal file
940
node_modules/eslint/lib/eslint/eslint-helpers.js
generated
vendored
Normal file
|
|
@ -0,0 +1,940 @@
|
|||
/**
|
||||
* @fileoverview Helper functions for ESLint class
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const fsp = fs.promises;
|
||||
const isGlob = require("is-glob");
|
||||
const hash = require("../cli-engine/hash");
|
||||
const minimatch = require("minimatch");
|
||||
const util = require("util");
|
||||
const fswalk = require("@nodelib/fs.walk");
|
||||
const globParent = require("glob-parent");
|
||||
const isPathInside = require("is-path-inside");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fixup references
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const doFsWalk = util.promisify(fswalk.walk);
|
||||
const Minimatch = minimatch.Minimatch;
|
||||
const MINIMATCH_OPTIONS = { dot: true };
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @typedef {Object} GlobSearch
|
||||
* @property {Array<string>} patterns The normalized patterns to use for a search.
|
||||
* @property {Array<string>} rawPatterns The patterns as entered by the user
|
||||
* before doing any normalization.
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Errors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The error type when no files match a glob.
|
||||
*/
|
||||
class NoFilesFoundError extends Error {
|
||||
|
||||
/**
|
||||
* @param {string} pattern The glob pattern which was not found.
|
||||
* @param {boolean} globEnabled If `false` then the pattern was a glob pattern, but glob was disabled.
|
||||
*/
|
||||
constructor(pattern, globEnabled) {
|
||||
super(`No files matching '${pattern}' were found${!globEnabled ? " (glob was disabled)" : ""}.`);
|
||||
this.messageTemplate = "file-not-found";
|
||||
this.messageData = { pattern, globDisabled: !globEnabled };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The error type when a search fails to match multiple patterns.
|
||||
*/
|
||||
class UnmatchedSearchPatternsError extends Error {
|
||||
|
||||
/**
|
||||
* @param {Object} options The options for the error.
|
||||
* @param {string} options.basePath The directory that was searched.
|
||||
* @param {Array<string>} options.unmatchedPatterns The glob patterns
|
||||
* which were not found.
|
||||
* @param {Array<string>} options.patterns The glob patterns that were
|
||||
* searched.
|
||||
* @param {Array<string>} options.rawPatterns The raw glob patterns that
|
||||
* were searched.
|
||||
*/
|
||||
constructor({ basePath, unmatchedPatterns, patterns, rawPatterns }) {
|
||||
super(`No files matching '${rawPatterns}' in '${basePath}' were found.`);
|
||||
this.basePath = basePath;
|
||||
this.unmatchedPatterns = unmatchedPatterns;
|
||||
this.patterns = patterns;
|
||||
this.rawPatterns = rawPatterns;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The error type when there are files matched by a glob, but all of them have been ignored.
|
||||
*/
|
||||
class AllFilesIgnoredError extends Error {
|
||||
|
||||
/**
|
||||
* @param {string} pattern The glob pattern which was not found.
|
||||
*/
|
||||
constructor(pattern) {
|
||||
super(`All files matched by '${pattern}' are ignored.`);
|
||||
this.messageTemplate = "all-files-ignored";
|
||||
this.messageData = { pattern };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// General Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check if a given value is a non-empty string or not.
|
||||
* @param {any} x The value to check.
|
||||
* @returns {boolean} `true` if `x` is a non-empty string.
|
||||
*/
|
||||
function isNonEmptyString(x) {
|
||||
return typeof x === "string" && x.trim() !== "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given value is an array of non-empty strings or not.
|
||||
* @param {any} x The value to check.
|
||||
* @returns {boolean} `true` if `x` is an array of non-empty strings.
|
||||
*/
|
||||
function isArrayOfNonEmptyString(x) {
|
||||
return Array.isArray(x) && x.every(isNonEmptyString);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// File-related Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Normalizes slashes in a file pattern to posix-style.
|
||||
* @param {string} pattern The pattern to replace slashes in.
|
||||
* @returns {string} The pattern with slashes normalized.
|
||||
*/
|
||||
function normalizeToPosix(pattern) {
|
||||
return pattern.replace(/\\/gu, "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string is a glob pattern or not.
|
||||
* @param {string} pattern A glob pattern.
|
||||
* @returns {boolean} `true` if the string is a glob pattern.
|
||||
*/
|
||||
function isGlobPattern(pattern) {
|
||||
return isGlob(path.sep === "\\" ? normalizeToPosix(pattern) : pattern);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if a given glob pattern will return any results.
|
||||
* Used primarily to help with useful error messages.
|
||||
* @param {Object} options The options for the function.
|
||||
* @param {string} options.basePath The directory to search.
|
||||
* @param {string} options.pattern A glob pattern to match.
|
||||
* @returns {Promise<boolean>} True if there is a glob match, false if not.
|
||||
*/
|
||||
function globMatch({ basePath, pattern }) {
|
||||
|
||||
let found = false;
|
||||
const patternToUse = path.isAbsolute(pattern)
|
||||
? normalizeToPosix(path.relative(basePath, pattern))
|
||||
: pattern;
|
||||
|
||||
const matcher = new Minimatch(patternToUse, MINIMATCH_OPTIONS);
|
||||
|
||||
const fsWalkSettings = {
|
||||
|
||||
deepFilter(entry) {
|
||||
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
|
||||
|
||||
return !found && matcher.match(relativePath, true);
|
||||
},
|
||||
|
||||
entryFilter(entry) {
|
||||
if (found || entry.dirent.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
|
||||
|
||||
if (matcher.match(relativePath)) {
|
||||
found = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise(resolve => {
|
||||
|
||||
// using a stream so we can exit early because we just need one match
|
||||
const globStream = fswalk.walkStream(basePath, fsWalkSettings);
|
||||
|
||||
globStream.on("data", () => {
|
||||
globStream.destroy();
|
||||
resolve(true);
|
||||
});
|
||||
|
||||
// swallow errors as they're not important here
|
||||
globStream.on("error", () => { });
|
||||
|
||||
globStream.on("end", () => {
|
||||
resolve(false);
|
||||
});
|
||||
globStream.read();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches a directory looking for matching glob patterns. This uses
|
||||
* the config array's logic to determine if a directory or file should
|
||||
* be ignored, so it is consistent with how ignoring works throughout
|
||||
* ESLint.
|
||||
* @param {Object} options The options for this function.
|
||||
* @param {string} options.basePath The directory to search.
|
||||
* @param {Array<string>} options.patterns An array of glob patterns
|
||||
* to match.
|
||||
* @param {Array<string>} options.rawPatterns An array of glob patterns
|
||||
* as the user inputted them. Used for errors.
|
||||
* @param {FlatConfigArray} options.configs The config array to use for
|
||||
* determining what to ignore.
|
||||
* @param {boolean} options.errorOnUnmatchedPattern Determines if an error
|
||||
* should be thrown when a pattern is unmatched.
|
||||
* @returns {Promise<Array<string>>} An array of matching file paths
|
||||
* or an empty array if there are no matches.
|
||||
* @throws {UnmatchedSearchPatternsErrror} If there is a pattern that doesn't
|
||||
* match any files.
|
||||
*/
|
||||
async function globSearch({
|
||||
basePath,
|
||||
patterns,
|
||||
rawPatterns,
|
||||
configs,
|
||||
errorOnUnmatchedPattern
|
||||
}) {
|
||||
|
||||
if (patterns.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/*
|
||||
* In this section we are converting the patterns into Minimatch
|
||||
* instances for performance reasons. Because we are doing the same
|
||||
* matches repeatedly, it's best to compile those patterns once and
|
||||
* reuse them multiple times.
|
||||
*
|
||||
* To do that, we convert any patterns with an absolute path into a
|
||||
* relative path and normalize it to Posix-style slashes. We also keep
|
||||
* track of the relative patterns to map them back to the original
|
||||
* patterns, which we need in order to throw an error if there are any
|
||||
* unmatched patterns.
|
||||
*/
|
||||
const relativeToPatterns = new Map();
|
||||
const matchers = patterns.map((pattern, i) => {
|
||||
const patternToUse = path.isAbsolute(pattern)
|
||||
? normalizeToPosix(path.relative(basePath, pattern))
|
||||
: pattern;
|
||||
|
||||
relativeToPatterns.set(patternToUse, patterns[i]);
|
||||
|
||||
return new Minimatch(patternToUse, MINIMATCH_OPTIONS);
|
||||
});
|
||||
|
||||
/*
|
||||
* We track unmatched patterns because we may want to throw an error when
|
||||
* they occur. To start, this set is initialized with all of the patterns.
|
||||
* Every time a match occurs, the pattern is removed from the set, making
|
||||
* it easy to tell if we have any unmatched patterns left at the end of
|
||||
* search.
|
||||
*/
|
||||
const unmatchedPatterns = new Set([...relativeToPatterns.keys()]);
|
||||
|
||||
const filePaths = (await doFsWalk(basePath, {
|
||||
|
||||
deepFilter(entry) {
|
||||
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
|
||||
const matchesPattern = matchers.some(matcher => matcher.match(relativePath, true));
|
||||
|
||||
return matchesPattern && !configs.isDirectoryIgnored(entry.path);
|
||||
},
|
||||
entryFilter(entry) {
|
||||
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
|
||||
|
||||
// entries may be directories or files so filter out directories
|
||||
if (entry.dirent.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Optimization: We need to track when patterns are left unmatched
|
||||
* and so we use `unmatchedPatterns` to do that. There is a bit of
|
||||
* complexity here because the same file can be matched by more than
|
||||
* one pattern. So, when we start, we actually need to test every
|
||||
* pattern against every file. Once we know there are no remaining
|
||||
* unmatched patterns, then we can switch to just looking for the
|
||||
* first matching pattern for improved speed.
|
||||
*/
|
||||
const matchesPattern = unmatchedPatterns.size > 0
|
||||
? matchers.reduce((previousValue, matcher) => {
|
||||
const pathMatches = matcher.match(relativePath);
|
||||
|
||||
/*
|
||||
* We updated the unmatched patterns set only if the path
|
||||
* matches and the file isn't ignored. If the file is
|
||||
* ignored, that means there wasn't a match for the
|
||||
* pattern so it should not be removed.
|
||||
*
|
||||
* Performance note: isFileIgnored() aggressively caches
|
||||
* results so there is no performance penalty for calling
|
||||
* it twice with the same argument.
|
||||
*/
|
||||
if (pathMatches && !configs.isFileIgnored(entry.path)) {
|
||||
unmatchedPatterns.delete(matcher.pattern);
|
||||
}
|
||||
|
||||
return pathMatches || previousValue;
|
||||
}, false)
|
||||
: matchers.some(matcher => matcher.match(relativePath));
|
||||
|
||||
return matchesPattern && !configs.isFileIgnored(entry.path);
|
||||
}
|
||||
|
||||
})).map(entry => entry.path);
|
||||
|
||||
// now check to see if we have any unmatched patterns
|
||||
if (errorOnUnmatchedPattern && unmatchedPatterns.size > 0) {
|
||||
throw new UnmatchedSearchPatternsError({
|
||||
basePath,
|
||||
unmatchedPatterns: [...unmatchedPatterns].map(
|
||||
pattern => relativeToPatterns.get(pattern)
|
||||
),
|
||||
patterns,
|
||||
rawPatterns
|
||||
});
|
||||
}
|
||||
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an error for unmatched patterns. The error will only contain information about the first one.
|
||||
* Checks to see if there are any ignored results for a given search.
|
||||
* @param {Object} options The options for this function.
|
||||
* @param {string} options.basePath The directory to search.
|
||||
* @param {Array<string>} options.patterns An array of glob patterns
|
||||
* that were used in the original search.
|
||||
* @param {Array<string>} options.rawPatterns An array of glob patterns
|
||||
* as the user inputted them. Used for errors.
|
||||
* @param {Array<string>} options.unmatchedPatterns A non-empty array of glob patterns
|
||||
* that were unmatched in the original search.
|
||||
* @returns {void} Always throws an error.
|
||||
* @throws {NoFilesFoundError} If the first unmatched pattern
|
||||
* doesn't match any files even when there are no ignores.
|
||||
* @throws {AllFilesIgnoredError} If the first unmatched pattern
|
||||
* matches some files when there are no ignores.
|
||||
*/
|
||||
async function throwErrorForUnmatchedPatterns({
|
||||
basePath,
|
||||
patterns,
|
||||
rawPatterns,
|
||||
unmatchedPatterns
|
||||
}) {
|
||||
|
||||
const pattern = unmatchedPatterns[0];
|
||||
const rawPattern = rawPatterns[patterns.indexOf(pattern)];
|
||||
|
||||
const patternHasMatch = await globMatch({
|
||||
basePath,
|
||||
pattern
|
||||
});
|
||||
|
||||
if (patternHasMatch) {
|
||||
throw new AllFilesIgnoredError(rawPattern);
|
||||
}
|
||||
|
||||
// if we get here there are truly no matches
|
||||
throw new NoFilesFoundError(rawPattern, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs multiple glob searches in parallel.
|
||||
* @param {Object} options The options for this function.
|
||||
* @param {Map<string,GlobSearch>} options.searches
|
||||
* An array of glob patterns to match.
|
||||
* @param {FlatConfigArray} options.configs The config array to use for
|
||||
* determining what to ignore.
|
||||
* @param {boolean} options.errorOnUnmatchedPattern Determines if an
|
||||
* unmatched glob pattern should throw an error.
|
||||
* @returns {Promise<Array<string>>} An array of matching file paths
|
||||
* or an empty array if there are no matches.
|
||||
*/
|
||||
async function globMultiSearch({ searches, configs, errorOnUnmatchedPattern }) {
|
||||
|
||||
/*
|
||||
* For convenience, we normalized the search map into an array of objects.
|
||||
* Next, we filter out all searches that have no patterns. This happens
|
||||
* primarily for the cwd, which is prepopulated in the searches map as an
|
||||
* optimization. However, if it has no patterns, it means all patterns
|
||||
* occur outside of the cwd and we can safely filter out that search.
|
||||
*/
|
||||
const normalizedSearches = [...searches].map(
|
||||
([basePath, { patterns, rawPatterns }]) => ({ basePath, patterns, rawPatterns })
|
||||
).filter(({ patterns }) => patterns.length > 0);
|
||||
|
||||
const results = await Promise.allSettled(
|
||||
normalizedSearches.map(
|
||||
({ basePath, patterns, rawPatterns }) => globSearch({
|
||||
basePath,
|
||||
patterns,
|
||||
rawPatterns,
|
||||
configs,
|
||||
errorOnUnmatchedPattern
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
const filePaths = [];
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
|
||||
const result = results[i];
|
||||
const currentSearch = normalizedSearches[i];
|
||||
|
||||
if (result.status === "fulfilled") {
|
||||
|
||||
// if the search was successful just add the results
|
||||
if (result.value.length > 0) {
|
||||
filePaths.push(...result.value);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we make it here then there was an error
|
||||
const error = result.reason;
|
||||
|
||||
// unexpected errors should be re-thrown
|
||||
if (!error.basePath) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (errorOnUnmatchedPattern) {
|
||||
|
||||
await throwErrorForUnmatchedPatterns({
|
||||
...currentSearch,
|
||||
unmatchedPatterns: error.unmatchedPatterns
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return [...new Set(filePaths)];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all files matching the options specified.
|
||||
* @param {Object} args The arguments objects.
|
||||
* @param {Array<string>} args.patterns An array of glob patterns.
|
||||
* @param {boolean} args.globInputPaths true to interpret glob patterns,
|
||||
* false to not interpret glob patterns.
|
||||
* @param {string} args.cwd The current working directory to find from.
|
||||
* @param {FlatConfigArray} args.configs The configs for the current run.
|
||||
* @param {boolean} args.errorOnUnmatchedPattern Determines if an unmatched pattern
|
||||
* should throw an error.
|
||||
* @returns {Promise<Array<string>>} The fully resolved file paths.
|
||||
* @throws {AllFilesIgnoredError} If there are no results due to an ignore pattern.
|
||||
* @throws {NoFilesFoundError} If no files matched the given patterns.
|
||||
*/
|
||||
async function findFiles({
|
||||
patterns,
|
||||
globInputPaths,
|
||||
cwd,
|
||||
configs,
|
||||
errorOnUnmatchedPattern
|
||||
}) {
|
||||
|
||||
const results = [];
|
||||
const missingPatterns = [];
|
||||
let globbyPatterns = [];
|
||||
let rawPatterns = [];
|
||||
const searches = new Map([[cwd, { patterns: globbyPatterns, rawPatterns: [] }]]);
|
||||
|
||||
// check to see if we have explicit files and directories
|
||||
const filePaths = patterns.map(filePath => path.resolve(cwd, filePath));
|
||||
const stats = await Promise.all(
|
||||
filePaths.map(
|
||||
filePath => fsp.stat(filePath).catch(() => { })
|
||||
)
|
||||
);
|
||||
|
||||
stats.forEach((stat, index) => {
|
||||
|
||||
const filePath = filePaths[index];
|
||||
const pattern = normalizeToPosix(patterns[index]);
|
||||
|
||||
if (stat) {
|
||||
|
||||
// files are added directly to the list
|
||||
if (stat.isFile()) {
|
||||
results.push({
|
||||
filePath,
|
||||
ignored: configs.isFileIgnored(filePath)
|
||||
});
|
||||
}
|
||||
|
||||
// directories need extensions attached
|
||||
if (stat.isDirectory()) {
|
||||
|
||||
// group everything in cwd together and split out others
|
||||
if (isPathInside(filePath, cwd)) {
|
||||
({ patterns: globbyPatterns, rawPatterns } = searches.get(cwd));
|
||||
} else {
|
||||
if (!searches.has(filePath)) {
|
||||
searches.set(filePath, { patterns: [], rawPatterns: [] });
|
||||
}
|
||||
({ patterns: globbyPatterns, rawPatterns } = searches.get(filePath));
|
||||
}
|
||||
|
||||
globbyPatterns.push(`${normalizeToPosix(filePath)}/**`);
|
||||
rawPatterns.push(pattern);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// save patterns for later use based on whether globs are enabled
|
||||
if (globInputPaths && isGlobPattern(filePath)) {
|
||||
|
||||
const basePath = globParent(filePath);
|
||||
|
||||
// group in cwd if possible and split out others
|
||||
if (isPathInside(basePath, cwd)) {
|
||||
({ patterns: globbyPatterns, rawPatterns } = searches.get(cwd));
|
||||
} else {
|
||||
if (!searches.has(basePath)) {
|
||||
searches.set(basePath, { patterns: [], rawPatterns: [] });
|
||||
}
|
||||
({ patterns: globbyPatterns, rawPatterns } = searches.get(basePath));
|
||||
}
|
||||
|
||||
globbyPatterns.push(filePath);
|
||||
rawPatterns.push(pattern);
|
||||
} else {
|
||||
missingPatterns.push(pattern);
|
||||
}
|
||||
});
|
||||
|
||||
// there were patterns that didn't match anything, tell the user
|
||||
if (errorOnUnmatchedPattern && missingPatterns.length) {
|
||||
throw new NoFilesFoundError(missingPatterns[0], globInputPaths);
|
||||
}
|
||||
|
||||
// now we are safe to do the search
|
||||
const globbyResults = await globMultiSearch({
|
||||
searches,
|
||||
configs,
|
||||
errorOnUnmatchedPattern
|
||||
});
|
||||
|
||||
return [
|
||||
...results,
|
||||
...globbyResults.map(filePath => ({
|
||||
filePath: path.resolve(filePath),
|
||||
ignored: false
|
||||
}))
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether a file exists at the given location
|
||||
* @param {string} resolvedPath A path from the CWD
|
||||
* @throws {Error} As thrown by `fs.statSync` or `fs.isFile`.
|
||||
* @returns {boolean} `true` if a file exists
|
||||
*/
|
||||
function fileExists(resolvedPath) {
|
||||
try {
|
||||
return fs.statSync(resolvedPath).isFile();
|
||||
} catch (error) {
|
||||
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
||||
return false;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a directory exists at the given location
|
||||
* @param {string} resolvedPath A path from the CWD
|
||||
* @throws {Error} As thrown by `fs.statSync` or `fs.isDirectory`.
|
||||
* @returns {boolean} `true` if a directory exists
|
||||
*/
|
||||
function directoryExists(resolvedPath) {
|
||||
try {
|
||||
return fs.statSync(resolvedPath).isDirectory();
|
||||
} catch (error) {
|
||||
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
||||
return false;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Results-related Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks if the given message is an error message.
|
||||
* @param {LintMessage} message The message to check.
|
||||
* @returns {boolean} Whether or not the message is an error message.
|
||||
* @private
|
||||
*/
|
||||
function isErrorMessage(message) {
|
||||
return message.severity === 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns result with warning by ignore settings
|
||||
* @param {string} filePath File path of checked code
|
||||
* @param {string} baseDir Absolute path of base directory
|
||||
* @returns {LintResult} Result with single warning
|
||||
* @private
|
||||
*/
|
||||
function createIgnoreResult(filePath, baseDir) {
|
||||
let message;
|
||||
const isHidden = filePath.split(path.sep)
|
||||
.find(segment => /^\./u.test(segment));
|
||||
const isInNodeModules = baseDir && path.relative(baseDir, filePath).startsWith("node_modules");
|
||||
|
||||
if (isHidden) {
|
||||
message = "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
|
||||
} else if (isInNodeModules) {
|
||||
message = "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
|
||||
} else {
|
||||
message = "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.";
|
||||
}
|
||||
|
||||
return {
|
||||
filePath: path.resolve(filePath),
|
||||
messages: [
|
||||
{
|
||||
fatal: false,
|
||||
severity: 1,
|
||||
message
|
||||
}
|
||||
],
|
||||
suppressedMessages: [],
|
||||
errorCount: 0,
|
||||
warningCount: 1,
|
||||
fatalErrorCount: 0,
|
||||
fixableErrorCount: 0,
|
||||
fixableWarningCount: 0
|
||||
};
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Options-related Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Check if a given value is a valid fix type or not.
|
||||
* @param {any} x The value to check.
|
||||
* @returns {boolean} `true` if `x` is valid fix type.
|
||||
*/
|
||||
function isFixType(x) {
|
||||
return x === "directive" || x === "problem" || x === "suggestion" || x === "layout";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given value is an array of fix types or not.
|
||||
* @param {any} x The value to check.
|
||||
* @returns {boolean} `true` if `x` is an array of fix types.
|
||||
*/
|
||||
function isFixTypeArray(x) {
|
||||
return Array.isArray(x) && x.every(isFixType);
|
||||
}
|
||||
|
||||
/**
|
||||
* The error for invalid options.
|
||||
*/
|
||||
class ESLintInvalidOptionsError extends Error {
|
||||
constructor(messages) {
|
||||
super(`Invalid Options:\n- ${messages.join("\n- ")}`);
|
||||
this.code = "ESLINT_INVALID_OPTIONS";
|
||||
Error.captureStackTrace(this, ESLintInvalidOptionsError);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and normalizes options for the wrapped CLIEngine instance.
|
||||
* @param {FlatESLintOptions} options The options to process.
|
||||
* @throws {ESLintInvalidOptionsError} If of any of a variety of type errors.
|
||||
* @returns {FlatESLintOptions} The normalized options.
|
||||
*/
|
||||
function processOptions({
|
||||
allowInlineConfig = true, // ← we cannot use `overrideConfig.noInlineConfig` instead because `allowInlineConfig` has side-effect that suppress warnings that show inline configs are ignored.
|
||||
baseConfig = null,
|
||||
cache = false,
|
||||
cacheLocation = ".eslintcache",
|
||||
cacheStrategy = "metadata",
|
||||
cwd = process.cwd(),
|
||||
errorOnUnmatchedPattern = true,
|
||||
fix = false,
|
||||
fixTypes = null, // ← should be null by default because if it's an array then it suppresses rules that don't have the `meta.type` property.
|
||||
globInputPaths = true,
|
||||
ignore = true,
|
||||
ignorePatterns = null,
|
||||
overrideConfig = null,
|
||||
overrideConfigFile = null,
|
||||
plugins = {},
|
||||
reportUnusedDisableDirectives = null, // ← should be null by default because if it's a string then it overrides the 'reportUnusedDisableDirectives' setting in config files. And we cannot use `overrideConfig.reportUnusedDisableDirectives` instead because we cannot configure the `error` severity with that.
|
||||
...unknownOptions
|
||||
}) {
|
||||
const errors = [];
|
||||
const unknownOptionKeys = Object.keys(unknownOptions);
|
||||
|
||||
if (unknownOptionKeys.length >= 1) {
|
||||
errors.push(`Unknown options: ${unknownOptionKeys.join(", ")}`);
|
||||
if (unknownOptionKeys.includes("cacheFile")) {
|
||||
errors.push("'cacheFile' has been removed. Please use the 'cacheLocation' option instead.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("configFile")) {
|
||||
errors.push("'configFile' has been removed. Please use the 'overrideConfigFile' option instead.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("envs")) {
|
||||
errors.push("'envs' has been removed.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("extensions")) {
|
||||
errors.push("'extensions' has been removed.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("resolvePluginsRelativeTo")) {
|
||||
errors.push("'resolvePluginsRelativeTo' has been removed.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("globals")) {
|
||||
errors.push("'globals' has been removed. Please use the 'overrideConfig.languageOptions.globals' option instead.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("ignorePath")) {
|
||||
errors.push("'ignorePath' has been removed.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("ignorePattern")) {
|
||||
errors.push("'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("parser")) {
|
||||
errors.push("'parser' has been removed. Please use the 'overrideConfig.languageOptions.parser' option instead.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("parserOptions")) {
|
||||
errors.push("'parserOptions' has been removed. Please use the 'overrideConfig.languageOptions.parserOptions' option instead.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("rules")) {
|
||||
errors.push("'rules' has been removed. Please use the 'overrideConfig.rules' option instead.");
|
||||
}
|
||||
if (unknownOptionKeys.includes("rulePaths")) {
|
||||
errors.push("'rulePaths' has been removed. Please define your rules using plugins.");
|
||||
}
|
||||
}
|
||||
if (typeof allowInlineConfig !== "boolean") {
|
||||
errors.push("'allowInlineConfig' must be a boolean.");
|
||||
}
|
||||
if (typeof baseConfig !== "object") {
|
||||
errors.push("'baseConfig' must be an object or null.");
|
||||
}
|
||||
if (typeof cache !== "boolean") {
|
||||
errors.push("'cache' must be a boolean.");
|
||||
}
|
||||
if (!isNonEmptyString(cacheLocation)) {
|
||||
errors.push("'cacheLocation' must be a non-empty string.");
|
||||
}
|
||||
if (
|
||||
cacheStrategy !== "metadata" &&
|
||||
cacheStrategy !== "content"
|
||||
) {
|
||||
errors.push("'cacheStrategy' must be any of \"metadata\", \"content\".");
|
||||
}
|
||||
if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) {
|
||||
errors.push("'cwd' must be an absolute path.");
|
||||
}
|
||||
if (typeof errorOnUnmatchedPattern !== "boolean") {
|
||||
errors.push("'errorOnUnmatchedPattern' must be a boolean.");
|
||||
}
|
||||
if (typeof fix !== "boolean" && typeof fix !== "function") {
|
||||
errors.push("'fix' must be a boolean or a function.");
|
||||
}
|
||||
if (fixTypes !== null && !isFixTypeArray(fixTypes)) {
|
||||
errors.push("'fixTypes' must be an array of any of \"directive\", \"problem\", \"suggestion\", and \"layout\".");
|
||||
}
|
||||
if (typeof globInputPaths !== "boolean") {
|
||||
errors.push("'globInputPaths' must be a boolean.");
|
||||
}
|
||||
if (typeof ignore !== "boolean") {
|
||||
errors.push("'ignore' must be a boolean.");
|
||||
}
|
||||
if (typeof overrideConfig !== "object") {
|
||||
errors.push("'overrideConfig' must be an object or null.");
|
||||
}
|
||||
if (!isNonEmptyString(overrideConfigFile) && overrideConfigFile !== null && overrideConfigFile !== true) {
|
||||
errors.push("'overrideConfigFile' must be a non-empty string, null, or true.");
|
||||
}
|
||||
if (typeof plugins !== "object") {
|
||||
errors.push("'plugins' must be an object or null.");
|
||||
} else if (plugins !== null && Object.keys(plugins).includes("")) {
|
||||
errors.push("'plugins' must not include an empty string.");
|
||||
}
|
||||
if (Array.isArray(plugins)) {
|
||||
errors.push("'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead.");
|
||||
}
|
||||
if (
|
||||
reportUnusedDisableDirectives !== "error" &&
|
||||
reportUnusedDisableDirectives !== "warn" &&
|
||||
reportUnusedDisableDirectives !== "off" &&
|
||||
reportUnusedDisableDirectives !== null
|
||||
) {
|
||||
errors.push("'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null.");
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
throw new ESLintInvalidOptionsError(errors);
|
||||
}
|
||||
|
||||
return {
|
||||
allowInlineConfig,
|
||||
baseConfig,
|
||||
cache,
|
||||
cacheLocation,
|
||||
cacheStrategy,
|
||||
|
||||
// when overrideConfigFile is true that means don't do config file lookup
|
||||
configFile: overrideConfigFile === true ? false : overrideConfigFile,
|
||||
overrideConfig,
|
||||
cwd,
|
||||
errorOnUnmatchedPattern,
|
||||
fix,
|
||||
fixTypes,
|
||||
globInputPaths,
|
||||
ignore,
|
||||
ignorePatterns,
|
||||
reportUnusedDisableDirectives
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Cache-related helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* return the cacheFile to be used by eslint, based on whether the provided parameter is
|
||||
* a directory or looks like a directory (ends in `path.sep`), in which case the file
|
||||
* name will be the `cacheFile/.cache_hashOfCWD`
|
||||
*
|
||||
* if cacheFile points to a file or looks like a file then in will just use that file
|
||||
* @param {string} cacheFile The name of file to be used to store the cache
|
||||
* @param {string} cwd Current working directory
|
||||
* @returns {string} the resolved path to the cache file
|
||||
*/
|
||||
function getCacheFile(cacheFile, cwd) {
|
||||
|
||||
/*
|
||||
* make sure the path separators are normalized for the environment/os
|
||||
* keeping the trailing path separator if present
|
||||
*/
|
||||
const normalizedCacheFile = path.normalize(cacheFile);
|
||||
|
||||
const resolvedCacheFile = path.resolve(cwd, normalizedCacheFile);
|
||||
const looksLikeADirectory = normalizedCacheFile.slice(-1) === path.sep;
|
||||
|
||||
/**
|
||||
* return the name for the cache file in case the provided parameter is a directory
|
||||
* @returns {string} the resolved path to the cacheFile
|
||||
*/
|
||||
function getCacheFileForDirectory() {
|
||||
return path.join(resolvedCacheFile, `.cache_${hash(cwd)}`);
|
||||
}
|
||||
|
||||
let fileStats;
|
||||
|
||||
try {
|
||||
fileStats = fs.lstatSync(resolvedCacheFile);
|
||||
} catch {
|
||||
fileStats = null;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* in case the file exists we need to verify if the provided path
|
||||
* is a directory or a file. If it is a directory we want to create a file
|
||||
* inside that directory
|
||||
*/
|
||||
if (fileStats) {
|
||||
|
||||
/*
|
||||
* is a directory or is a file, but the original file the user provided
|
||||
* looks like a directory but `path.resolve` removed the `last path.sep`
|
||||
* so we need to still treat this like a directory
|
||||
*/
|
||||
if (fileStats.isDirectory() || looksLikeADirectory) {
|
||||
return getCacheFileForDirectory();
|
||||
}
|
||||
|
||||
// is file so just use that file
|
||||
return resolvedCacheFile;
|
||||
}
|
||||
|
||||
/*
|
||||
* here we known the file or directory doesn't exist,
|
||||
* so we will try to infer if its a directory if it looks like a directory
|
||||
* for the current operating system.
|
||||
*/
|
||||
|
||||
// if the last character passed is a path separator we assume is a directory
|
||||
if (looksLikeADirectory) {
|
||||
return getCacheFileForDirectory();
|
||||
}
|
||||
|
||||
return resolvedCacheFile;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
isGlobPattern,
|
||||
directoryExists,
|
||||
fileExists,
|
||||
findFiles,
|
||||
|
||||
isNonEmptyString,
|
||||
isArrayOfNonEmptyString,
|
||||
|
||||
createIgnoreResult,
|
||||
isErrorMessage,
|
||||
|
||||
processOptions,
|
||||
|
||||
getCacheFile
|
||||
};
|
||||
73
node_modules/eslint/lib/eslint/eslint.js
generated
vendored
73
node_modules/eslint/lib/eslint/eslint.js
generated
vendored
|
|
@ -32,9 +32,17 @@ const { version } = require("../../package.json");
|
|||
/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
|
||||
/** @typedef {import("../shared/types").ConfigData} ConfigData */
|
||||
/** @typedef {import("../shared/types").LintMessage} LintMessage */
|
||||
/** @typedef {import("../shared/types").SuppressedLintMessage} SuppressedLintMessage */
|
||||
/** @typedef {import("../shared/types").Plugin} Plugin */
|
||||
/** @typedef {import("../shared/types").Rule} Rule */
|
||||
/** @typedef {import("./load-formatter").Formatter} Formatter */
|
||||
/** @typedef {import("../shared/types").LintResult} LintResult */
|
||||
/** @typedef {import("../shared/types").ResultsMeta} ResultsMeta */
|
||||
|
||||
/**
|
||||
* The main formatter object.
|
||||
* @typedef LoadedFormatter
|
||||
* @property {(results: LintResult[], resultsMeta: ResultsMeta) => string | Promise<string>} format format function.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The options with which to configure the ESLint instance.
|
||||
|
|
@ -54,7 +62,7 @@ const { version } = require("../../package.json");
|
|||
* @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
|
||||
* @property {ConfigData} [overrideConfig] Override config object, overrides all configs used with this instance
|
||||
* @property {string} [overrideConfigFile] The configuration file to use.
|
||||
* @property {Record<string,Plugin>} [plugins] An array of plugin implementations.
|
||||
* @property {Record<string,Plugin>|null} [plugins] Preloaded plugins. This is a map-like object, keys are plugin IDs and each value is implementation.
|
||||
* @property {"error" | "warn" | "off"} [reportUnusedDisableDirectives] the severity to report unused eslint-disable directives.
|
||||
* @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD.
|
||||
* @property {string[]} [rulePaths] An array of directories to load custom rules from.
|
||||
|
|
@ -68,20 +76,6 @@ const { version } = require("../../package.json");
|
|||
* @property {Object} definition The plugin definition.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A linting result.
|
||||
* @typedef {Object} LintResult
|
||||
* @property {string} filePath The path to the file that was linted.
|
||||
* @property {LintMessage[]} messages All of the messages for the result.
|
||||
* @property {number} errorCount Number of errors for the result.
|
||||
* @property {number} warningCount Number of warnings for the result.
|
||||
* @property {number} fixableErrorCount Number of fixable errors for the result.
|
||||
* @property {number} fixableWarningCount Number of fixable warnings for the result.
|
||||
* @property {string} [source] The source code of the file that was linted.
|
||||
* @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
|
||||
* @property {DeprecatedRuleInfo[]} usedDeprecatedRules The list of used deprecated rules.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Private members for the `ESLint` instance.
|
||||
* @typedef {Object} ESLintPrivateMembers
|
||||
|
|
@ -111,9 +105,9 @@ function isNonEmptyString(x) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if a given value is an array of non-empty stringss or not.
|
||||
* Check if a given value is an array of non-empty strings or not.
|
||||
* @param {any} x The value to check.
|
||||
* @returns {boolean} `true` if `x` is an array of non-empty stringss.
|
||||
* @returns {boolean} `true` if `x` is an array of non-empty strings.
|
||||
*/
|
||||
function isArrayOfNonEmptyString(x) {
|
||||
return Array.isArray(x) && x.every(isNonEmptyString);
|
||||
|
|
@ -125,7 +119,7 @@ function isArrayOfNonEmptyString(x) {
|
|||
* @returns {boolean} `true` if `x` is valid fix type.
|
||||
*/
|
||||
function isFixType(x) {
|
||||
return x === "problem" || x === "suggestion" || x === "layout";
|
||||
return x === "directive" || x === "problem" || x === "suggestion" || x === "layout";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -151,6 +145,7 @@ class ESLintInvalidOptionsError extends Error {
|
|||
/**
|
||||
* Validates and normalizes options for the wrapped CLIEngine instance.
|
||||
* @param {ESLintOptions} options The options to process.
|
||||
* @throws {ESLintInvalidOptionsError} If of any of a variety of type errors.
|
||||
* @returns {ESLintOptions} The normalized options.
|
||||
*/
|
||||
function processOptions({
|
||||
|
|
@ -237,7 +232,7 @@ function processOptions({
|
|||
errors.push("'fix' must be a boolean or a function.");
|
||||
}
|
||||
if (fixTypes !== null && !isFixTypeArray(fixTypes)) {
|
||||
errors.push("'fixTypes' must be an array of any of \"problem\", \"suggestion\", and \"layout\".");
|
||||
errors.push("'fixTypes' must be an array of any of \"directive\", \"problem\", \"suggestion\", and \"layout\".");
|
||||
}
|
||||
if (typeof globInputPaths !== "boolean") {
|
||||
errors.push("'globInputPaths' must be a boolean.");
|
||||
|
|
@ -421,6 +416,9 @@ function compareResultsByFilePath(a, b) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main API.
|
||||
*/
|
||||
class ESLint {
|
||||
|
||||
/**
|
||||
|
|
@ -429,26 +427,13 @@ class ESLint {
|
|||
*/
|
||||
constructor(options = {}) {
|
||||
const processedOptions = processOptions(options);
|
||||
const cliEngine = new CLIEngine(processedOptions);
|
||||
const cliEngine = new CLIEngine(processedOptions, { preloadedPlugins: options.plugins });
|
||||
const {
|
||||
additionalPluginPool,
|
||||
configArrayFactory,
|
||||
lastConfigArrays
|
||||
} = getCLIEngineInternalSlots(cliEngine);
|
||||
let updated = false;
|
||||
|
||||
/*
|
||||
* Address `plugins` to add plugin implementations.
|
||||
* Operate the `additionalPluginPool` internal slot directly to avoid
|
||||
* using `addPlugin(id, plugin)` method that resets cache everytime.
|
||||
*/
|
||||
if (options.plugins) {
|
||||
for (const [id, plugin] of Object.entries(options.plugins)) {
|
||||
additionalPluginPool.set(id, plugin);
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Address `overrideConfig` to set override config.
|
||||
* Operate the `configArrayFactory` internal slot directly because this
|
||||
|
|
@ -529,6 +514,9 @@ class ESLint {
|
|||
for (const { ruleId } of result.messages) {
|
||||
resultRuleIds.add(ruleId);
|
||||
}
|
||||
for (const { ruleId } of result.suppressedMessages) {
|
||||
resultRuleIds.add(ruleId);
|
||||
}
|
||||
}
|
||||
|
||||
// create a map of all rules in the results
|
||||
|
|
@ -612,12 +600,12 @@ class ESLint {
|
|||
* The following values are allowed:
|
||||
* - `undefined` ... Load `stylish` builtin formatter.
|
||||
* - A builtin formatter name ... Load the builtin formatter.
|
||||
* - A thirdparty formatter name:
|
||||
* - A third-party formatter name:
|
||||
* - `foo` → `eslint-formatter-foo`
|
||||
* - `@foo` → `@foo/eslint-formatter`
|
||||
* - `@foo/bar` → `@foo/eslint-formatter-bar`
|
||||
* - A file path ... Load the file.
|
||||
* @returns {Promise<Formatter>} A promise resolving to the formatter object.
|
||||
* @returns {Promise<LoadedFormatter>} A promise resolving to the formatter object.
|
||||
* This promise will be rejected if the given formatter was not found or not
|
||||
* a function.
|
||||
*/
|
||||
|
|
@ -626,7 +614,7 @@ class ESLint {
|
|||
throw new Error("'name' must be a string");
|
||||
}
|
||||
|
||||
const { cliEngine } = privateMembersMap.get(this);
|
||||
const { cliEngine, options } = privateMembersMap.get(this);
|
||||
const formatter = cliEngine.getFormatter(name);
|
||||
|
||||
if (typeof formatter !== "function") {
|
||||
|
|
@ -637,15 +625,20 @@ class ESLint {
|
|||
|
||||
/**
|
||||
* The main formatter method.
|
||||
* @param {LintResults[]} results The lint results to format.
|
||||
* @returns {string} The formatted lint results.
|
||||
* @param {LintResult[]} results The lint results to format.
|
||||
* @param {ResultsMeta} resultsMeta Warning count and max threshold.
|
||||
* @returns {string | Promise<string>} The formatted lint results.
|
||||
*/
|
||||
format(results) {
|
||||
format(results, resultsMeta) {
|
||||
let rulesMeta = null;
|
||||
|
||||
results.sort(compareResultsByFilePath);
|
||||
|
||||
return formatter(results, {
|
||||
...resultsMeta,
|
||||
get cwd() {
|
||||
return options.cwd;
|
||||
},
|
||||
get rulesMeta() {
|
||||
if (!rulesMeta) {
|
||||
rulesMeta = createRulesMeta(cliEngine.getRules());
|
||||
|
|
|
|||
1182
node_modules/eslint/lib/eslint/flat-eslint.js
generated
vendored
Normal file
1182
node_modules/eslint/lib/eslint/flat-eslint.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
4
node_modules/eslint/lib/eslint/index.js
generated
vendored
4
node_modules/eslint/lib/eslint/index.js
generated
vendored
|
|
@ -1,7 +1,9 @@
|
|||
"use strict";
|
||||
|
||||
const { ESLint } = require("./eslint");
|
||||
const { FlatESLint } = require("./flat-eslint");
|
||||
|
||||
module.exports = {
|
||||
ESLint
|
||||
ESLint,
|
||||
FlatESLint
|
||||
};
|
||||
|
|
|
|||
348
node_modules/eslint/lib/init/autoconfig.js
generated
vendored
348
node_modules/eslint/lib/init/autoconfig.js
generated
vendored
|
|
@ -1,348 +0,0 @@
|
|||
/**
|
||||
* @fileoverview Used for creating a suggested configuration based on project code.
|
||||
* @author Ian VanSchooten
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const equal = require("fast-deep-equal"),
|
||||
recConfig = require("../../conf/eslint-recommended"),
|
||||
ConfigOps = require("@eslint/eslintrc/lib/shared/config-ops"),
|
||||
{ Linter } = require("../linter"),
|
||||
configRule = require("./config-rule");
|
||||
|
||||
const debug = require("debug")("eslint:autoconfig");
|
||||
const linter = new Linter();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Data
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const MAX_CONFIG_COMBINATIONS = 17, // 16 combinations + 1 for severity only
|
||||
RECOMMENDED_CONFIG_NAME = "eslint:recommended";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Information about a rule configuration, in the context of a Registry.
|
||||
* @typedef {Object} registryItem
|
||||
* @param {ruleConfig} config A valid configuration for the rule
|
||||
* @param {number} specificity The number of elements in the ruleConfig array
|
||||
* @param {number} errorCount The number of errors encountered when linting with the config
|
||||
*/
|
||||
|
||||
/**
|
||||
* This callback is used to measure execution status in a progress bar
|
||||
* @callback progressCallback
|
||||
* @param {number} The total number of times the callback will be called.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create registryItems for rules
|
||||
* @param {rulesConfig} rulesConfig Hash of rule names and arrays of ruleConfig items
|
||||
* @returns {Object} registryItems for each rule in provided rulesConfig
|
||||
*/
|
||||
function makeRegistryItems(rulesConfig) {
|
||||
return Object.keys(rulesConfig).reduce((accumulator, ruleId) => {
|
||||
accumulator[ruleId] = rulesConfig[ruleId].map(config => ({
|
||||
config,
|
||||
specificity: config.length || 1,
|
||||
errorCount: void 0
|
||||
}));
|
||||
return accumulator;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object in which to store rule configs and error counts
|
||||
*
|
||||
* Unless a rulesConfig is provided at construction, the registry will not contain
|
||||
* any rules, only methods. This will be useful for building up registries manually.
|
||||
*
|
||||
* Registry class
|
||||
*/
|
||||
class Registry {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {rulesConfig} [rulesConfig] Hash of rule names and arrays of possible configurations
|
||||
*/
|
||||
constructor(rulesConfig) {
|
||||
this.rules = (rulesConfig) ? makeRegistryItems(rulesConfig) : {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the registry with core rule configs.
|
||||
*
|
||||
* It will set the registry's `rule` property to an object having rule names
|
||||
* as keys and an array of registryItems as values.
|
||||
* @returns {void}
|
||||
*/
|
||||
populateFromCoreRules() {
|
||||
const rulesConfig = configRule.createCoreRuleConfigs(/* noDeprecated = */ true);
|
||||
|
||||
this.rules = makeRegistryItems(rulesConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates sets of rule configurations which can be used for linting
|
||||
* and initializes registry errors to zero for those configurations (side effect).
|
||||
*
|
||||
* This combines as many rules together as possible, such that the first sets
|
||||
* in the array will have the highest number of rules configured, and later sets
|
||||
* will have fewer and fewer, as not all rules have the same number of possible
|
||||
* configurations.
|
||||
*
|
||||
* The length of the returned array will be <= MAX_CONFIG_COMBINATIONS.
|
||||
* @returns {Object[]} "rules" configurations to use for linting
|
||||
*/
|
||||
buildRuleSets() {
|
||||
let idx = 0;
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
ruleSets = [];
|
||||
|
||||
/**
|
||||
* Add a rule configuration from the registry to the ruleSets
|
||||
*
|
||||
* This is broken out into its own function so that it doesn't need to be
|
||||
* created inside of the while loop.
|
||||
* @param {string} rule The ruleId to add.
|
||||
* @returns {void}
|
||||
*/
|
||||
const addRuleToRuleSet = function(rule) {
|
||||
|
||||
/*
|
||||
* This check ensures that there is a rule configuration and that
|
||||
* it has fewer than the max combinations allowed.
|
||||
* If it has too many configs, we will only use the most basic of
|
||||
* the possible configurations.
|
||||
*/
|
||||
const hasFewCombos = (this.rules[rule].length <= MAX_CONFIG_COMBINATIONS);
|
||||
|
||||
if (this.rules[rule][idx] && (hasFewCombos || this.rules[rule][idx].specificity <= 2)) {
|
||||
|
||||
/*
|
||||
* If the rule has too many possible combinations, only take
|
||||
* simple ones, avoiding objects.
|
||||
*/
|
||||
if (!hasFewCombos && typeof this.rules[rule][idx].config[1] === "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
ruleSets[idx] = ruleSets[idx] || {};
|
||||
ruleSets[idx][rule] = this.rules[rule][idx].config;
|
||||
|
||||
/*
|
||||
* Initialize errorCount to zero, since this is a config which
|
||||
* will be linted.
|
||||
*/
|
||||
this.rules[rule][idx].errorCount = 0;
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
while (ruleSets.length === idx) {
|
||||
ruleIds.forEach(addRuleToRuleSet);
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
return ruleSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from the registry with a non-zero number of errors
|
||||
*
|
||||
* Note: this also removes rule configurations which were not linted
|
||||
* (meaning, they have an undefined errorCount).
|
||||
* @returns {void}
|
||||
*/
|
||||
stripFailingConfigs() {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
newRegistry = new Registry();
|
||||
|
||||
newRegistry.rules = Object.assign({}, this.rules);
|
||||
ruleIds.forEach(ruleId => {
|
||||
const errorFreeItems = newRegistry.rules[ruleId].filter(registryItem => (registryItem.errorCount === 0));
|
||||
|
||||
if (errorFreeItems.length > 0) {
|
||||
newRegistry.rules[ruleId] = errorFreeItems;
|
||||
} else {
|
||||
delete newRegistry.rules[ruleId];
|
||||
}
|
||||
});
|
||||
|
||||
return newRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes rule configurations which were not included in a ruleSet
|
||||
* @returns {void}
|
||||
*/
|
||||
stripExtraConfigs() {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
newRegistry = new Registry();
|
||||
|
||||
newRegistry.rules = Object.assign({}, this.rules);
|
||||
ruleIds.forEach(ruleId => {
|
||||
newRegistry.rules[ruleId] = newRegistry.rules[ruleId].filter(registryItem => (typeof registryItem.errorCount !== "undefined"));
|
||||
});
|
||||
|
||||
return newRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a registry of rules which had no error-free configs.
|
||||
* The new registry is intended to be analyzed to determine whether its rules
|
||||
* should be disabled or set to warning.
|
||||
* @returns {Registry} A registry of failing rules.
|
||||
*/
|
||||
getFailingRulesRegistry() {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
failingRegistry = new Registry();
|
||||
|
||||
ruleIds.forEach(ruleId => {
|
||||
const failingConfigs = this.rules[ruleId].filter(registryItem => (registryItem.errorCount > 0));
|
||||
|
||||
if (failingConfigs && failingConfigs.length === this.rules[ruleId].length) {
|
||||
failingRegistry.rules[ruleId] = failingConfigs;
|
||||
}
|
||||
});
|
||||
|
||||
return failingRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an eslint config for any rules which only have one configuration
|
||||
* in the registry.
|
||||
* @returns {Object} An eslint config with rules section populated
|
||||
*/
|
||||
createConfig() {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
config = { rules: {} };
|
||||
|
||||
ruleIds.forEach(ruleId => {
|
||||
if (this.rules[ruleId].length === 1) {
|
||||
config.rules[ruleId] = this.rules[ruleId][0].config;
|
||||
}
|
||||
});
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a cloned registry containing only configs with a desired specificity
|
||||
* @param {number} specificity Only keep configs with this specificity
|
||||
* @returns {Registry} A registry of rules
|
||||
*/
|
||||
filterBySpecificity(specificity) {
|
||||
const ruleIds = Object.keys(this.rules),
|
||||
newRegistry = new Registry();
|
||||
|
||||
newRegistry.rules = Object.assign({}, this.rules);
|
||||
ruleIds.forEach(ruleId => {
|
||||
newRegistry.rules[ruleId] = this.rules[ruleId].filter(registryItem => (registryItem.specificity === specificity));
|
||||
});
|
||||
|
||||
return newRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lint SourceCodes against all configurations in the registry, and record results
|
||||
* @param {Object[]} sourceCodes SourceCode objects for each filename
|
||||
* @param {Object} config ESLint config object
|
||||
* @param {progressCallback} [cb] Optional callback for reporting execution status
|
||||
* @returns {Registry} New registry with errorCount populated
|
||||
*/
|
||||
lintSourceCode(sourceCodes, config, cb) {
|
||||
let lintedRegistry = new Registry();
|
||||
|
||||
lintedRegistry.rules = Object.assign({}, this.rules);
|
||||
|
||||
const ruleSets = lintedRegistry.buildRuleSets();
|
||||
|
||||
lintedRegistry = lintedRegistry.stripExtraConfigs();
|
||||
|
||||
debug("Linting with all possible rule combinations");
|
||||
|
||||
const filenames = Object.keys(sourceCodes);
|
||||
const totalFilesLinting = filenames.length * ruleSets.length;
|
||||
|
||||
filenames.forEach(filename => {
|
||||
debug(`Linting file: ${filename}`);
|
||||
|
||||
let ruleSetIdx = 0;
|
||||
|
||||
ruleSets.forEach(ruleSet => {
|
||||
const lintConfig = Object.assign({}, config, { rules: ruleSet });
|
||||
const lintResults = linter.verify(sourceCodes[filename], lintConfig);
|
||||
|
||||
lintResults.forEach(result => {
|
||||
|
||||
/*
|
||||
* It is possible that the error is from a configuration comment
|
||||
* in a linted file, in which case there may not be a config
|
||||
* set in this ruleSetIdx.
|
||||
* (https://github.com/eslint/eslint/issues/5992)
|
||||
* (https://github.com/eslint/eslint/issues/7860)
|
||||
*/
|
||||
if (
|
||||
lintedRegistry.rules[result.ruleId] &&
|
||||
lintedRegistry.rules[result.ruleId][ruleSetIdx]
|
||||
) {
|
||||
lintedRegistry.rules[result.ruleId][ruleSetIdx].errorCount += 1;
|
||||
}
|
||||
});
|
||||
|
||||
ruleSetIdx += 1;
|
||||
|
||||
if (cb) {
|
||||
cb(totalFilesLinting); // eslint-disable-line node/callback-return
|
||||
}
|
||||
});
|
||||
|
||||
// Deallocate for GC
|
||||
sourceCodes[filename] = null;
|
||||
});
|
||||
|
||||
return lintedRegistry;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract rule configuration into eslint:recommended where possible.
|
||||
*
|
||||
* This will return a new config with `["extends": [ ..., "eslint:recommended"]` and
|
||||
* only the rules which have configurations different from the recommended config.
|
||||
* @param {Object} config config object
|
||||
* @returns {Object} config object using `"extends": ["eslint:recommended"]`
|
||||
*/
|
||||
function extendFromRecommended(config) {
|
||||
const newConfig = Object.assign({}, config);
|
||||
|
||||
ConfigOps.normalizeToStrings(newConfig);
|
||||
|
||||
const recRules = Object.keys(recConfig.rules).filter(ruleId => ConfigOps.isErrorSeverity(recConfig.rules[ruleId]));
|
||||
|
||||
recRules.forEach(ruleId => {
|
||||
if (equal(recConfig.rules[ruleId], newConfig.rules[ruleId])) {
|
||||
delete newConfig.rules[ruleId];
|
||||
}
|
||||
});
|
||||
newConfig.extends.unshift(RECOMMENDED_CONFIG_NAME);
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
Registry,
|
||||
extendFromRecommended
|
||||
};
|
||||
144
node_modules/eslint/lib/init/config-file.js
generated
vendored
144
node_modules/eslint/lib/init/config-file.js
generated
vendored
|
|
@ -1,144 +0,0 @@
|
|||
/**
|
||||
* @fileoverview Helper to locate and load configuration files.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const fs = require("fs"),
|
||||
path = require("path"),
|
||||
stringify = require("json-stable-stringify-without-jsonify");
|
||||
|
||||
const debug = require("debug")("eslint:config-file");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines sort order for object keys for json-stable-stringify
|
||||
*
|
||||
* see: https://github.com/samn/json-stable-stringify#cmp
|
||||
* @param {Object} a The first comparison object ({key: akey, value: avalue})
|
||||
* @param {Object} b The second comparison object ({key: bkey, value: bvalue})
|
||||
* @returns {number} 1 or -1, used in stringify cmp method
|
||||
*/
|
||||
function sortByKey(a, b) {
|
||||
return a.key > b.key ? 1 : -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Writes a configuration file in JSON format.
|
||||
* @param {Object} config The configuration object to write.
|
||||
* @param {string} filePath The filename to write to.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function writeJSONConfigFile(config, filePath) {
|
||||
debug(`Writing JSON config file: ${filePath}`);
|
||||
|
||||
const content = `${stringify(config, { cmp: sortByKey, space: 4 })}\n`;
|
||||
|
||||
fs.writeFileSync(filePath, content, "utf8");
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a configuration file in YAML format.
|
||||
* @param {Object} config The configuration object to write.
|
||||
* @param {string} filePath The filename to write to.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function writeYAMLConfigFile(config, filePath) {
|
||||
debug(`Writing YAML config file: ${filePath}`);
|
||||
|
||||
// lazy load YAML to improve performance when not used
|
||||
const yaml = require("js-yaml");
|
||||
|
||||
const content = yaml.safeDump(config, { sortKeys: true });
|
||||
|
||||
fs.writeFileSync(filePath, content, "utf8");
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a configuration file in JavaScript format.
|
||||
* @param {Object} config The configuration object to write.
|
||||
* @param {string} filePath The filename to write to.
|
||||
* @throws {Error} If an error occurs linting the config file contents.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function writeJSConfigFile(config, filePath) {
|
||||
debug(`Writing JS config file: ${filePath}`);
|
||||
|
||||
let contentToWrite;
|
||||
const stringifiedContent = `module.exports = ${stringify(config, { cmp: sortByKey, space: 4 })};\n`;
|
||||
|
||||
try {
|
||||
const { CLIEngine } = require("../cli-engine");
|
||||
const linter = new CLIEngine({
|
||||
baseConfig: config,
|
||||
fix: true,
|
||||
useEslintrc: false
|
||||
});
|
||||
const report = linter.executeOnText(stringifiedContent);
|
||||
|
||||
contentToWrite = report.results[0].output || stringifiedContent;
|
||||
} catch (e) {
|
||||
debug("Error linting JavaScript config file, writing unlinted version");
|
||||
const errorMessage = e.message;
|
||||
|
||||
contentToWrite = stringifiedContent;
|
||||
e.message = "An error occurred while generating your JavaScript config file. ";
|
||||
e.message += "A config file was still generated, but the config file itself may not follow your linting rules.";
|
||||
e.message += `\nError: ${errorMessage}`;
|
||||
throw e;
|
||||
} finally {
|
||||
fs.writeFileSync(filePath, contentToWrite, "utf8");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a configuration file.
|
||||
* @param {Object} config The configuration object to write.
|
||||
* @param {string} filePath The filename to write to.
|
||||
* @returns {void}
|
||||
* @throws {Error} When an unknown file type is specified.
|
||||
* @private
|
||||
*/
|
||||
function write(config, filePath) {
|
||||
switch (path.extname(filePath)) {
|
||||
case ".js":
|
||||
case ".cjs":
|
||||
writeJSConfigFile(config, filePath);
|
||||
break;
|
||||
|
||||
case ".json":
|
||||
writeJSONConfigFile(config, filePath);
|
||||
break;
|
||||
|
||||
case ".yaml":
|
||||
case ".yml":
|
||||
writeYAMLConfigFile(config, filePath);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("Can't write to unknown file type.");
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
write
|
||||
};
|
||||
704
node_modules/eslint/lib/init/config-initializer.js
generated
vendored
704
node_modules/eslint/lib/init/config-initializer.js
generated
vendored
|
|
@ -1,704 +0,0 @@
|
|||
/**
|
||||
* @fileoverview Config initialization wizard.
|
||||
* @author Ilya Volodin
|
||||
*/
|
||||
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const util = require("util"),
|
||||
path = require("path"),
|
||||
fs = require("fs"),
|
||||
enquirer = require("enquirer"),
|
||||
ProgressBar = require("progress"),
|
||||
semver = require("semver"),
|
||||
espree = require("espree"),
|
||||
recConfig = require("../../conf/eslint-recommended"),
|
||||
ConfigOps = require("@eslint/eslintrc/lib/shared/config-ops"),
|
||||
log = require("../shared/logging"),
|
||||
naming = require("@eslint/eslintrc/lib/shared/naming"),
|
||||
ModuleResolver = require("../shared/relative-module-resolver"),
|
||||
autoconfig = require("./autoconfig.js"),
|
||||
ConfigFile = require("./config-file"),
|
||||
npmUtils = require("./npm-utils"),
|
||||
{ getSourceCodeOfFiles } = require("./source-code-utils");
|
||||
|
||||
const debug = require("debug")("eslint:config-initializer");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* istanbul ignore next: hard to test fs function */
|
||||
/**
|
||||
* Create .eslintrc file in the current working directory
|
||||
* @param {Object} config object that contains user's answers
|
||||
* @param {string} format The file format to write to.
|
||||
* @returns {void}
|
||||
*/
|
||||
function writeFile(config, format) {
|
||||
|
||||
// default is .js
|
||||
let extname = ".js";
|
||||
|
||||
if (format === "YAML") {
|
||||
extname = ".yml";
|
||||
} else if (format === "JSON") {
|
||||
extname = ".json";
|
||||
} else if (format === "JavaScript") {
|
||||
const pkgJSONPath = npmUtils.findPackageJson();
|
||||
|
||||
if (pkgJSONPath) {
|
||||
const pkgJSONContents = JSON.parse(fs.readFileSync(pkgJSONPath, "utf8"));
|
||||
|
||||
if (pkgJSONContents.type === "module") {
|
||||
extname = ".cjs";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const installedESLint = config.installedESLint;
|
||||
|
||||
delete config.installedESLint;
|
||||
|
||||
ConfigFile.write(config, `./.eslintrc${extname}`);
|
||||
log.info(`Successfully created .eslintrc${extname} file in ${process.cwd()}`);
|
||||
|
||||
if (installedESLint) {
|
||||
log.info("ESLint was installed locally. We recommend using this local copy instead of your globally-installed copy.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the peer dependencies of the given module.
|
||||
* This adds the gotten value to cache at the first time, then reuses it.
|
||||
* In a process, this function is called twice, but `npmUtils.fetchPeerDependencies` needs to access network which is relatively slow.
|
||||
* @param {string} moduleName The module name to get.
|
||||
* @returns {Object} The peer dependencies of the given module.
|
||||
* This object is the object of `peerDependencies` field of `package.json`.
|
||||
* Returns null if npm was not found.
|
||||
*/
|
||||
function getPeerDependencies(moduleName) {
|
||||
let result = getPeerDependencies.cache.get(moduleName);
|
||||
|
||||
if (!result) {
|
||||
log.info(`Checking peerDependencies of ${moduleName}`);
|
||||
|
||||
result = npmUtils.fetchPeerDependencies(moduleName);
|
||||
getPeerDependencies.cache.set(moduleName, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
getPeerDependencies.cache = new Map();
|
||||
|
||||
/**
|
||||
* Return necessary plugins, configs, parsers, etc. based on the config
|
||||
* @param {Object} config config object
|
||||
* @param {boolean} [installESLint=true] If `false` is given, it does not install eslint.
|
||||
* @returns {string[]} An array of modules to be installed.
|
||||
*/
|
||||
function getModulesList(config, installESLint) {
|
||||
const modules = {};
|
||||
|
||||
// Create a list of modules which should be installed based on config
|
||||
if (config.plugins) {
|
||||
for (const plugin of config.plugins) {
|
||||
const moduleName = naming.normalizePackageName(plugin, "eslint-plugin");
|
||||
|
||||
modules[moduleName] = "latest";
|
||||
}
|
||||
}
|
||||
if (config.extends) {
|
||||
const extendList = Array.isArray(config.extends) ? config.extends : [config.extends];
|
||||
|
||||
for (const extend of extendList) {
|
||||
if (extend.startsWith("eslint:") || extend.startsWith("plugin:")) {
|
||||
continue;
|
||||
}
|
||||
const moduleName = naming.normalizePackageName(extend, "eslint-config");
|
||||
|
||||
modules[moduleName] = "latest";
|
||||
Object.assign(
|
||||
modules,
|
||||
getPeerDependencies(`${moduleName}@latest`)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const parser = config.parser || (config.parserOptions && config.parserOptions.parser);
|
||||
|
||||
if (parser) {
|
||||
modules[parser] = "latest";
|
||||
}
|
||||
|
||||
if (installESLint === false) {
|
||||
delete modules.eslint;
|
||||
} else {
|
||||
const installStatus = npmUtils.checkDevDeps(["eslint"]);
|
||||
|
||||
// Mark to show messages if it's new installation of eslint.
|
||||
if (installStatus.eslint === false) {
|
||||
log.info("Local ESLint installation not found.");
|
||||
modules.eslint = modules.eslint || "latest";
|
||||
config.installedESLint = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Object.keys(modules).map(name => `${name}@${modules[name]}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the `rules` of a config by examining a user's source code
|
||||
*
|
||||
* Note: This clones the config object and returns a new config to avoid mutating
|
||||
* the original config parameter.
|
||||
* @param {Object} answers answers received from enquirer
|
||||
* @param {Object} config config object
|
||||
* @returns {Object} config object with configured rules
|
||||
*/
|
||||
function configureRules(answers, config) {
|
||||
const BAR_TOTAL = 20,
|
||||
BAR_SOURCE_CODE_TOTAL = 4,
|
||||
newConfig = Object.assign({}, config),
|
||||
disabledConfigs = {};
|
||||
let sourceCodes,
|
||||
registry;
|
||||
|
||||
// Set up a progress bar, as this process can take a long time
|
||||
const bar = new ProgressBar("Determining Config: :percent [:bar] :elapseds elapsed, eta :etas ", {
|
||||
width: 30,
|
||||
total: BAR_TOTAL
|
||||
});
|
||||
|
||||
bar.tick(0); // Shows the progress bar
|
||||
|
||||
// Get the SourceCode of all chosen files
|
||||
const patterns = answers.patterns.split(/[\s]+/u);
|
||||
|
||||
try {
|
||||
sourceCodes = getSourceCodeOfFiles(patterns, { baseConfig: newConfig, useEslintrc: false }, total => {
|
||||
bar.tick((BAR_SOURCE_CODE_TOTAL / total));
|
||||
});
|
||||
} catch (e) {
|
||||
log.info("\n");
|
||||
throw e;
|
||||
}
|
||||
const fileQty = Object.keys(sourceCodes).length;
|
||||
|
||||
if (fileQty === 0) {
|
||||
log.info("\n");
|
||||
throw new Error("Automatic Configuration failed. No files were able to be parsed.");
|
||||
}
|
||||
|
||||
// Create a registry of rule configs
|
||||
registry = new autoconfig.Registry();
|
||||
registry.populateFromCoreRules();
|
||||
|
||||
// Lint all files with each rule config in the registry
|
||||
registry = registry.lintSourceCode(sourceCodes, newConfig, total => {
|
||||
bar.tick((BAR_TOTAL - BAR_SOURCE_CODE_TOTAL) / total); // Subtract out ticks used at beginning
|
||||
});
|
||||
debug(`\nRegistry: ${util.inspect(registry.rules, { depth: null })}`);
|
||||
|
||||
// Create a list of recommended rules, because we don't want to disable them
|
||||
const recRules = Object.keys(recConfig.rules).filter(ruleId => ConfigOps.isErrorSeverity(recConfig.rules[ruleId]));
|
||||
|
||||
// Find and disable rules which had no error-free configuration
|
||||
const failingRegistry = registry.getFailingRulesRegistry();
|
||||
|
||||
Object.keys(failingRegistry.rules).forEach(ruleId => {
|
||||
|
||||
// If the rule is recommended, set it to error, otherwise disable it
|
||||
disabledConfigs[ruleId] = (recRules.indexOf(ruleId) !== -1) ? 2 : 0;
|
||||
});
|
||||
|
||||
// Now that we know which rules to disable, strip out configs with errors
|
||||
registry = registry.stripFailingConfigs();
|
||||
|
||||
/*
|
||||
* If there is only one config that results in no errors for a rule, we should use it.
|
||||
* createConfig will only add rules that have one configuration in the registry.
|
||||
*/
|
||||
const singleConfigs = registry.createConfig().rules;
|
||||
|
||||
/*
|
||||
* The "sweet spot" for number of options in a config seems to be two (severity plus one option).
|
||||
* Very often, a third option (usually an object) is available to address
|
||||
* edge cases, exceptions, or unique situations. We will prefer to use a config with
|
||||
* specificity of two.
|
||||
*/
|
||||
const specTwoConfigs = registry.filterBySpecificity(2).createConfig().rules;
|
||||
|
||||
// Maybe a specific combination using all three options works
|
||||
const specThreeConfigs = registry.filterBySpecificity(3).createConfig().rules;
|
||||
|
||||
// If all else fails, try to use the default (severity only)
|
||||
const defaultConfigs = registry.filterBySpecificity(1).createConfig().rules;
|
||||
|
||||
// Combine configs in reverse priority order (later take precedence)
|
||||
newConfig.rules = Object.assign({}, disabledConfigs, defaultConfigs, specThreeConfigs, specTwoConfigs, singleConfigs);
|
||||
|
||||
// Make sure progress bar has finished (floating point rounding)
|
||||
bar.update(BAR_TOTAL);
|
||||
|
||||
// Log out some stats to let the user know what happened
|
||||
const finalRuleIds = Object.keys(newConfig.rules);
|
||||
const totalRules = finalRuleIds.length;
|
||||
const enabledRules = finalRuleIds.filter(ruleId => (newConfig.rules[ruleId] !== 0)).length;
|
||||
const resultMessage = [
|
||||
`\nEnabled ${enabledRules} out of ${totalRules}`,
|
||||
`rules based on ${fileQty}`,
|
||||
`file${(fileQty === 1) ? "." : "s."}`
|
||||
].join(" ");
|
||||
|
||||
log.info(resultMessage);
|
||||
|
||||
ConfigOps.normalizeToStrings(newConfig);
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* process user's answers and create config object
|
||||
* @param {Object} answers answers received from enquirer
|
||||
* @returns {Object} config object
|
||||
*/
|
||||
function processAnswers(answers) {
|
||||
let config = {
|
||||
rules: {},
|
||||
env: {},
|
||||
parserOptions: {},
|
||||
extends: []
|
||||
};
|
||||
|
||||
config.parserOptions.ecmaVersion = espree.latestEcmaVersion;
|
||||
config.env.es2021 = true;
|
||||
|
||||
// set the module type
|
||||
if (answers.moduleType === "esm") {
|
||||
config.parserOptions.sourceType = "module";
|
||||
} else if (answers.moduleType === "commonjs") {
|
||||
config.env.commonjs = true;
|
||||
}
|
||||
|
||||
// add in browser and node environments if necessary
|
||||
answers.env.forEach(env => {
|
||||
config.env[env] = true;
|
||||
});
|
||||
|
||||
// add in library information
|
||||
if (answers.framework === "react") {
|
||||
config.parserOptions.ecmaFeatures = {
|
||||
jsx: true
|
||||
};
|
||||
config.plugins = ["react"];
|
||||
config.extends.push("plugin:react/recommended");
|
||||
} else if (answers.framework === "vue") {
|
||||
config.plugins = ["vue"];
|
||||
config.extends.push("plugin:vue/essential");
|
||||
}
|
||||
|
||||
if (answers.typescript) {
|
||||
if (answers.framework === "vue") {
|
||||
config.parserOptions.parser = "@typescript-eslint/parser";
|
||||
} else {
|
||||
config.parser = "@typescript-eslint/parser";
|
||||
}
|
||||
|
||||
if (Array.isArray(config.plugins)) {
|
||||
config.plugins.push("@typescript-eslint");
|
||||
} else {
|
||||
config.plugins = ["@typescript-eslint"];
|
||||
}
|
||||
}
|
||||
|
||||
// setup rules based on problems/style enforcement preferences
|
||||
if (answers.purpose === "problems") {
|
||||
config.extends.unshift("eslint:recommended");
|
||||
} else if (answers.purpose === "style") {
|
||||
if (answers.source === "prompt") {
|
||||
config.extends.unshift("eslint:recommended");
|
||||
config.rules.indent = ["error", answers.indent];
|
||||
config.rules.quotes = ["error", answers.quotes];
|
||||
config.rules["linebreak-style"] = ["error", answers.linebreak];
|
||||
config.rules.semi = ["error", answers.semi ? "always" : "never"];
|
||||
} else if (answers.source === "auto") {
|
||||
config = configureRules(answers, config);
|
||||
config = autoconfig.extendFromRecommended(config);
|
||||
}
|
||||
}
|
||||
if (answers.typescript && config.extends.includes("eslint:recommended")) {
|
||||
config.extends.push("plugin:@typescript-eslint/recommended");
|
||||
}
|
||||
|
||||
// normalize extends
|
||||
if (config.extends.length === 0) {
|
||||
delete config.extends;
|
||||
} else if (config.extends.length === 1) {
|
||||
config.extends = config.extends[0];
|
||||
}
|
||||
|
||||
ConfigOps.normalizeToStrings(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the local ESLint.
|
||||
* @returns {string|null} The version. If the local ESLint was not found, returns null.
|
||||
*/
|
||||
function getLocalESLintVersion() {
|
||||
try {
|
||||
const eslintPath = ModuleResolver.resolve("eslint", path.join(process.cwd(), "__placeholder__.js"));
|
||||
const eslint = require(eslintPath);
|
||||
|
||||
return eslint.linter.version || null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the shareable config name of the chosen style guide.
|
||||
* @param {Object} answers The answers object.
|
||||
* @returns {string} The shareable config name.
|
||||
*/
|
||||
function getStyleGuideName(answers) {
|
||||
if (answers.styleguide === "airbnb" && answers.framework !== "react") {
|
||||
return "airbnb-base";
|
||||
}
|
||||
return answers.styleguide;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the local ESLint version conflicts with the required version of the chosen shareable config.
|
||||
* @param {Object} answers The answers object.
|
||||
* @returns {boolean} `true` if the local ESLint is found then it conflicts with the required version of the chosen shareable config.
|
||||
*/
|
||||
function hasESLintVersionConflict(answers) {
|
||||
|
||||
// Get the local ESLint version.
|
||||
const localESLintVersion = getLocalESLintVersion();
|
||||
|
||||
if (!localESLintVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the required range of ESLint version.
|
||||
const configName = getStyleGuideName(answers);
|
||||
const moduleName = `eslint-config-${configName}@latest`;
|
||||
const peerDependencies = getPeerDependencies(moduleName) || {};
|
||||
const requiredESLintVersionRange = peerDependencies.eslint;
|
||||
|
||||
if (!requiredESLintVersionRange) {
|
||||
return false;
|
||||
}
|
||||
|
||||
answers.localESLintVersion = localESLintVersion;
|
||||
answers.requiredESLintVersionRange = requiredESLintVersionRange;
|
||||
|
||||
// Check the version.
|
||||
if (semver.satisfies(localESLintVersion, requiredESLintVersionRange)) {
|
||||
answers.installESLint = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install modules.
|
||||
* @param {string[]} modules Modules to be installed.
|
||||
* @returns {void}
|
||||
*/
|
||||
function installModules(modules) {
|
||||
log.info(`Installing ${modules.join(", ")}`);
|
||||
npmUtils.installSyncSaveDev(modules);
|
||||
}
|
||||
|
||||
/* istanbul ignore next: no need to test enquirer */
|
||||
/**
|
||||
* Ask user to install modules.
|
||||
* @param {string[]} modules Array of modules to be installed.
|
||||
* @param {boolean} packageJsonExists Indicates if package.json is existed.
|
||||
* @returns {Promise} Answer that indicates if user wants to install.
|
||||
*/
|
||||
function askInstallModules(modules, packageJsonExists) {
|
||||
|
||||
// If no modules, do nothing.
|
||||
if (modules.length === 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
log.info("The config that you've selected requires the following dependencies:\n");
|
||||
log.info(modules.join(" "));
|
||||
return enquirer.prompt([
|
||||
{
|
||||
type: "toggle",
|
||||
name: "executeInstallation",
|
||||
message: "Would you like to install them now with npm?",
|
||||
enabled: "Yes",
|
||||
disabled: "No",
|
||||
initial: 1,
|
||||
skip() {
|
||||
return !(modules.length && packageJsonExists);
|
||||
},
|
||||
result(input) {
|
||||
return this.skipped ? null : input;
|
||||
}
|
||||
}
|
||||
]).then(({ executeInstallation }) => {
|
||||
if (executeInstallation) {
|
||||
installModules(modules);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* istanbul ignore next: no need to test enquirer */
|
||||
/**
|
||||
* Ask use a few questions on command prompt
|
||||
* @returns {Promise} The promise with the result of the prompt
|
||||
*/
|
||||
function promptUser() {
|
||||
|
||||
return enquirer.prompt([
|
||||
{
|
||||
type: "select",
|
||||
name: "purpose",
|
||||
message: "How would you like to use ESLint?",
|
||||
|
||||
// The returned number matches the name value of nth in the choices array.
|
||||
initial: 1,
|
||||
choices: [
|
||||
{ message: "To check syntax only", name: "syntax" },
|
||||
{ message: "To check syntax and find problems", name: "problems" },
|
||||
{ message: "To check syntax, find problems, and enforce code style", name: "style" }
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "moduleType",
|
||||
message: "What type of modules does your project use?",
|
||||
initial: 0,
|
||||
choices: [
|
||||
{ message: "JavaScript modules (import/export)", name: "esm" },
|
||||
{ message: "CommonJS (require/exports)", name: "commonjs" },
|
||||
{ message: "None of these", name: "none" }
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "framework",
|
||||
message: "Which framework does your project use?",
|
||||
initial: 0,
|
||||
choices: [
|
||||
{ message: "React", name: "react" },
|
||||
{ message: "Vue.js", name: "vue" },
|
||||
{ message: "None of these", name: "none" }
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "toggle",
|
||||
name: "typescript",
|
||||
message: "Does your project use TypeScript?",
|
||||
enabled: "Yes",
|
||||
disabled: "No",
|
||||
initial: 0
|
||||
},
|
||||
{
|
||||
type: "multiselect",
|
||||
name: "env",
|
||||
message: "Where does your code run?",
|
||||
hint: "(Press <space> to select, <a> to toggle all, <i> to invert selection)",
|
||||
initial: 0,
|
||||
choices: [
|
||||
{ message: "Browser", name: "browser" },
|
||||
{ message: "Node", name: "node" }
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "source",
|
||||
message: "How would you like to define a style for your project?",
|
||||
choices: [
|
||||
{ message: "Use a popular style guide", name: "guide" },
|
||||
{ message: "Answer questions about your style", name: "prompt" },
|
||||
{ message: "Inspect your JavaScript file(s)", name: "auto" }
|
||||
],
|
||||
skip() {
|
||||
return this.state.answers.purpose !== "style";
|
||||
},
|
||||
result(input) {
|
||||
return this.skipped ? null : input;
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "styleguide",
|
||||
message: "Which style guide do you want to follow?",
|
||||
choices: [
|
||||
{ message: "Airbnb: https://github.com/airbnb/javascript", name: "airbnb" },
|
||||
{ message: "Standard: https://github.com/standard/standard", name: "standard" },
|
||||
{ message: "Google: https://github.com/google/eslint-config-google", name: "google" },
|
||||
{ message: "XO: https://github.com/xojs/eslint-config-xo", name: "xo" }
|
||||
],
|
||||
skip() {
|
||||
this.state.answers.packageJsonExists = npmUtils.checkPackageJson();
|
||||
return !(this.state.answers.source === "guide" && this.state.answers.packageJsonExists);
|
||||
},
|
||||
result(input) {
|
||||
return this.skipped ? null : input;
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
name: "patterns",
|
||||
message: "Which file(s), path(s), or glob(s) should be examined?",
|
||||
skip() {
|
||||
return this.state.answers.source !== "auto";
|
||||
},
|
||||
validate(input) {
|
||||
if (!this.skipped && input.trim().length === 0 && input.trim() !== ",") {
|
||||
return "You must tell us what code to examine. Try again.";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "format",
|
||||
message: "What format do you want your config file to be in?",
|
||||
initial: 0,
|
||||
choices: ["JavaScript", "YAML", "JSON"]
|
||||
},
|
||||
{
|
||||
type: "toggle",
|
||||
name: "installESLint",
|
||||
message() {
|
||||
const { answers } = this.state;
|
||||
const verb = semver.ltr(answers.localESLintVersion, answers.requiredESLintVersionRange)
|
||||
? "upgrade"
|
||||
: "downgrade";
|
||||
|
||||
return `The style guide "${answers.styleguide}" requires eslint@${answers.requiredESLintVersionRange}. You are currently using eslint@${answers.localESLintVersion}.\n Do you want to ${verb}?`;
|
||||
},
|
||||
enabled: "Yes",
|
||||
disabled: "No",
|
||||
initial: 1,
|
||||
skip() {
|
||||
return !(this.state.answers.source === "guide" && this.state.answers.packageJsonExists && hasESLintVersionConflict(this.state.answers));
|
||||
},
|
||||
result(input) {
|
||||
return this.skipped ? null : input;
|
||||
}
|
||||
}
|
||||
]).then(earlyAnswers => {
|
||||
|
||||
// early exit if no style guide is necessary
|
||||
if (earlyAnswers.purpose !== "style") {
|
||||
const config = processAnswers(earlyAnswers);
|
||||
const modules = getModulesList(config);
|
||||
|
||||
return askInstallModules(modules, earlyAnswers.packageJsonExists)
|
||||
.then(() => writeFile(config, earlyAnswers.format));
|
||||
}
|
||||
|
||||
// early exit if you are using a style guide
|
||||
if (earlyAnswers.source === "guide") {
|
||||
if (!earlyAnswers.packageJsonExists) {
|
||||
log.info("A package.json is necessary to install plugins such as style guides. Run `npm init` to create a package.json file and try again.");
|
||||
return void 0;
|
||||
}
|
||||
if (earlyAnswers.installESLint === false && !semver.satisfies(earlyAnswers.localESLintVersion, earlyAnswers.requiredESLintVersionRange)) {
|
||||
log.info(`Note: it might not work since ESLint's version is mismatched with the ${earlyAnswers.styleguide} config.`);
|
||||
}
|
||||
if (earlyAnswers.styleguide === "airbnb" && earlyAnswers.framework !== "react") {
|
||||
earlyAnswers.styleguide = "airbnb-base";
|
||||
}
|
||||
|
||||
const config = processAnswers(earlyAnswers);
|
||||
|
||||
if (Array.isArray(config.extends)) {
|
||||
config.extends.push(earlyAnswers.styleguide);
|
||||
} else if (config.extends) {
|
||||
config.extends = [config.extends, earlyAnswers.styleguide];
|
||||
} else {
|
||||
config.extends = [earlyAnswers.styleguide];
|
||||
}
|
||||
|
||||
const modules = getModulesList(config);
|
||||
|
||||
return askInstallModules(modules, earlyAnswers.packageJsonExists)
|
||||
.then(() => writeFile(config, earlyAnswers.format));
|
||||
|
||||
}
|
||||
|
||||
if (earlyAnswers.source === "auto") {
|
||||
const combinedAnswers = Object.assign({}, earlyAnswers);
|
||||
const config = processAnswers(combinedAnswers);
|
||||
const modules = getModulesList(config);
|
||||
|
||||
return askInstallModules(modules).then(() => writeFile(config, earlyAnswers.format));
|
||||
}
|
||||
|
||||
// continue with the style questions otherwise...
|
||||
return enquirer.prompt([
|
||||
{
|
||||
type: "select",
|
||||
name: "indent",
|
||||
message: "What style of indentation do you use?",
|
||||
initial: 0,
|
||||
choices: [{ message: "Tabs", name: "tab" }, { message: "Spaces", name: 4 }]
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "quotes",
|
||||
message: "What quotes do you use for strings?",
|
||||
initial: 0,
|
||||
choices: [{ message: "Double", name: "double" }, { message: "Single", name: "single" }]
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "linebreak",
|
||||
message: "What line endings do you use?",
|
||||
initial: 0,
|
||||
choices: [{ message: "Unix", name: "unix" }, { message: "Windows", name: "windows" }]
|
||||
},
|
||||
{
|
||||
type: "toggle",
|
||||
name: "semi",
|
||||
message: "Do you require semicolons?",
|
||||
enabled: "Yes",
|
||||
disabled: "No",
|
||||
initial: 1
|
||||
}
|
||||
]).then(answers => {
|
||||
const totalAnswers = Object.assign({}, earlyAnswers, answers);
|
||||
|
||||
const config = processAnswers(totalAnswers);
|
||||
const modules = getModulesList(config);
|
||||
|
||||
return askInstallModules(modules).then(() => writeFile(config, earlyAnswers.format));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const init = {
|
||||
getModulesList,
|
||||
hasESLintVersionConflict,
|
||||
installModules,
|
||||
processAnswers,
|
||||
writeFile,
|
||||
/* istanbul ignore next */initializeConfig() {
|
||||
return promptUser();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = init;
|
||||
317
node_modules/eslint/lib/init/config-rule.js
generated
vendored
317
node_modules/eslint/lib/init/config-rule.js
generated
vendored
|
|
@ -1,317 +0,0 @@
|
|||
/**
|
||||
* @fileoverview Create configurations for a rule
|
||||
* @author Ian VanSchooten
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const builtInRules = require("../rules");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Wrap all of the elements of an array into arrays.
|
||||
* @param {*[]} xs Any array.
|
||||
* @returns {Array[]} An array of arrays.
|
||||
*/
|
||||
function explodeArray(xs) {
|
||||
return xs.reduce((accumulator, x) => {
|
||||
accumulator.push([x]);
|
||||
return accumulator;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix two arrays such that each element of the second array is concatenated
|
||||
* onto each element of the first array.
|
||||
*
|
||||
* For example:
|
||||
* combineArrays([a, [b, c]], [x, y]); // -> [[a, x], [a, y], [b, c, x], [b, c, y]]
|
||||
* @param {Array} arr1 The first array to combine.
|
||||
* @param {Array} arr2 The second array to combine.
|
||||
* @returns {Array} A mixture of the elements of the first and second arrays.
|
||||
*/
|
||||
function combineArrays(arr1, arr2) {
|
||||
const res = [];
|
||||
|
||||
if (arr1.length === 0) {
|
||||
return explodeArray(arr2);
|
||||
}
|
||||
if (arr2.length === 0) {
|
||||
return explodeArray(arr1);
|
||||
}
|
||||
arr1.forEach(x1 => {
|
||||
arr2.forEach(x2 => {
|
||||
res.push([].concat(x1, x2));
|
||||
});
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group together valid rule configurations based on object properties
|
||||
*
|
||||
* e.g.:
|
||||
* groupByProperty([
|
||||
* {before: true},
|
||||
* {before: false},
|
||||
* {after: true},
|
||||
* {after: false}
|
||||
* ]);
|
||||
*
|
||||
* will return:
|
||||
* [
|
||||
* [{before: true}, {before: false}],
|
||||
* [{after: true}, {after: false}]
|
||||
* ]
|
||||
* @param {Object[]} objects Array of objects, each with one property/value pair
|
||||
* @returns {Array[]} Array of arrays of objects grouped by property
|
||||
*/
|
||||
function groupByProperty(objects) {
|
||||
const groupedObj = objects.reduce((accumulator, obj) => {
|
||||
const prop = Object.keys(obj)[0];
|
||||
|
||||
accumulator[prop] = accumulator[prop] ? accumulator[prop].concat(obj) : [obj];
|
||||
return accumulator;
|
||||
}, {});
|
||||
|
||||
return Object.keys(groupedObj).map(prop => groupedObj[prop]);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Configuration settings for a rule.
|
||||
*
|
||||
* A configuration can be a single number (severity), or an array where the first
|
||||
* element in the array is the severity, and is the only required element.
|
||||
* Configs may also have one or more additional elements to specify rule
|
||||
* configuration or options.
|
||||
* @typedef {Array|number} ruleConfig
|
||||
* @param {number} 0 The rule's severity (0, 1, 2).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object whose keys are rule names and values are arrays of valid ruleConfig items
|
||||
* which should be linted against the target source code to determine error counts.
|
||||
* (a ruleConfigSet.ruleConfigs).
|
||||
*
|
||||
* e.g. rulesConfig = {
|
||||
* "comma-dangle": [2, [2, "always"], [2, "always-multiline"], [2, "never"]],
|
||||
* "no-console": [2]
|
||||
* }
|
||||
* @typedef rulesConfig
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Create valid rule configurations by combining two arrays,
|
||||
* with each array containing multiple objects each with a
|
||||
* single property/value pair and matching properties.
|
||||
*
|
||||
* e.g.:
|
||||
* combinePropertyObjects(
|
||||
* [{before: true}, {before: false}],
|
||||
* [{after: true}, {after: false}]
|
||||
* );
|
||||
*
|
||||
* will return:
|
||||
* [
|
||||
* {before: true, after: true},
|
||||
* {before: true, after: false},
|
||||
* {before: false, after: true},
|
||||
* {before: false, after: false}
|
||||
* ]
|
||||
* @param {Object[]} objArr1 Single key/value objects, all with the same key
|
||||
* @param {Object[]} objArr2 Single key/value objects, all with another key
|
||||
* @returns {Object[]} Combined objects for each combination of input properties and values
|
||||
*/
|
||||
function combinePropertyObjects(objArr1, objArr2) {
|
||||
const res = [];
|
||||
|
||||
if (objArr1.length === 0) {
|
||||
return objArr2;
|
||||
}
|
||||
if (objArr2.length === 0) {
|
||||
return objArr1;
|
||||
}
|
||||
objArr1.forEach(obj1 => {
|
||||
objArr2.forEach(obj2 => {
|
||||
const combinedObj = {};
|
||||
const obj1Props = Object.keys(obj1);
|
||||
const obj2Props = Object.keys(obj2);
|
||||
|
||||
obj1Props.forEach(prop1 => {
|
||||
combinedObj[prop1] = obj1[prop1];
|
||||
});
|
||||
obj2Props.forEach(prop2 => {
|
||||
combinedObj[prop2] = obj2[prop2];
|
||||
});
|
||||
res.push(combinedObj);
|
||||
});
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a rule configuration set
|
||||
*
|
||||
* A rule configuration set is an array of configurations that are valid for a
|
||||
* given rule. For example, the configuration set for the "semi" rule could be:
|
||||
*
|
||||
* ruleConfigSet.ruleConfigs // -> [[2], [2, "always"], [2, "never"]]
|
||||
*
|
||||
* Rule configuration set class
|
||||
*/
|
||||
class RuleConfigSet {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {ruleConfig[]} configs Valid rule configurations
|
||||
*/
|
||||
constructor(configs) {
|
||||
|
||||
/**
|
||||
* Stored valid rule configurations for this instance
|
||||
* @type {Array}
|
||||
*/
|
||||
this.ruleConfigs = configs || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a severity level to the front of all configs in the instance.
|
||||
* This should only be called after all configs have been added to the instance.
|
||||
* @returns {void}
|
||||
*/
|
||||
addErrorSeverity() {
|
||||
const severity = 2;
|
||||
|
||||
this.ruleConfigs = this.ruleConfigs.map(config => {
|
||||
config.unshift(severity);
|
||||
return config;
|
||||
});
|
||||
|
||||
// Add a single config at the beginning consisting of only the severity
|
||||
this.ruleConfigs.unshift(severity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add rule configs from an array of strings (schema enums)
|
||||
* @param {string[]} enums Array of valid rule options (e.g. ["always", "never"])
|
||||
* @returns {void}
|
||||
*/
|
||||
addEnums(enums) {
|
||||
this.ruleConfigs = this.ruleConfigs.concat(combineArrays(this.ruleConfigs, enums));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add rule configurations from a schema object
|
||||
* @param {Object} obj Schema item with type === "object"
|
||||
* @returns {boolean} true if at least one schema for the object could be generated, false otherwise
|
||||
*/
|
||||
addObject(obj) {
|
||||
const objectConfigSet = {
|
||||
objectConfigs: [],
|
||||
add(property, values) {
|
||||
for (let idx = 0; idx < values.length; idx++) {
|
||||
const optionObj = {};
|
||||
|
||||
optionObj[property] = values[idx];
|
||||
this.objectConfigs.push(optionObj);
|
||||
}
|
||||
},
|
||||
|
||||
combine() {
|
||||
this.objectConfigs = groupByProperty(this.objectConfigs).reduce((accumulator, objArr) => combinePropertyObjects(accumulator, objArr), []);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The object schema could have multiple independent properties.
|
||||
* If any contain enums or booleans, they can be added and then combined
|
||||
*/
|
||||
Object.keys(obj.properties).forEach(prop => {
|
||||
if (obj.properties[prop].enum) {
|
||||
objectConfigSet.add(prop, obj.properties[prop].enum);
|
||||
}
|
||||
if (obj.properties[prop].type && obj.properties[prop].type === "boolean") {
|
||||
objectConfigSet.add(prop, [true, false]);
|
||||
}
|
||||
});
|
||||
objectConfigSet.combine();
|
||||
|
||||
if (objectConfigSet.objectConfigs.length > 0) {
|
||||
this.ruleConfigs = this.ruleConfigs.concat(combineArrays(this.ruleConfigs, objectConfigSet.objectConfigs));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate valid rule configurations based on a schema object
|
||||
* @param {Object} schema A rule's schema object
|
||||
* @returns {Array[]} Valid rule configurations
|
||||
*/
|
||||
function generateConfigsFromSchema(schema) {
|
||||
const configSet = new RuleConfigSet();
|
||||
|
||||
if (Array.isArray(schema)) {
|
||||
for (const opt of schema) {
|
||||
if (opt.enum) {
|
||||
configSet.addEnums(opt.enum);
|
||||
} else if (opt.type && opt.type === "object") {
|
||||
if (!configSet.addObject(opt)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO (IanVS): support oneOf
|
||||
} else {
|
||||
|
||||
// If we don't know how to fill in this option, don't fill in any of the following options.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
configSet.addErrorSeverity();
|
||||
return configSet.ruleConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate possible rule configurations for all of the core rules
|
||||
* @param {boolean} noDeprecated Indicates whether ignores deprecated rules or not.
|
||||
* @returns {rulesConfig} Hash of rule names and arrays of possible configurations
|
||||
*/
|
||||
function createCoreRuleConfigs(noDeprecated = false) {
|
||||
return Array.from(builtInRules).reduce((accumulator, [id, rule]) => {
|
||||
const schema = (typeof rule === "function") ? rule.schema : rule.meta.schema;
|
||||
const isDeprecated = (typeof rule === "function") ? rule.deprecated : rule.meta.deprecated;
|
||||
|
||||
if (noDeprecated && isDeprecated) {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
accumulator[id] = generateConfigsFromSchema(schema);
|
||||
return accumulator;
|
||||
}, {});
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
generateConfigsFromSchema,
|
||||
createCoreRuleConfigs
|
||||
};
|
||||
178
node_modules/eslint/lib/init/npm-utils.js
generated
vendored
178
node_modules/eslint/lib/init/npm-utils.js
generated
vendored
|
|
@ -1,178 +0,0 @@
|
|||
/**
|
||||
* @fileoverview Utility for executing npm commands.
|
||||
* @author Ian VanSchooten
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const fs = require("fs"),
|
||||
spawn = require("cross-spawn"),
|
||||
path = require("path"),
|
||||
log = require("../shared/logging");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Find the closest package.json file, starting at process.cwd (by default),
|
||||
* and working up to root.
|
||||
* @param {string} [startDir=process.cwd()] Starting directory
|
||||
* @returns {string} Absolute path to closest package.json file
|
||||
*/
|
||||
function findPackageJson(startDir) {
|
||||
let dir = path.resolve(startDir || process.cwd());
|
||||
|
||||
do {
|
||||
const pkgFile = path.join(dir, "package.json");
|
||||
|
||||
if (!fs.existsSync(pkgFile) || !fs.statSync(pkgFile).isFile()) {
|
||||
dir = path.join(dir, "..");
|
||||
continue;
|
||||
}
|
||||
return pkgFile;
|
||||
} while (dir !== path.resolve(dir, ".."));
|
||||
return null;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Install node modules synchronously and save to devDependencies in package.json
|
||||
* @param {string|string[]} packages Node module or modules to install
|
||||
* @returns {void}
|
||||
*/
|
||||
function installSyncSaveDev(packages) {
|
||||
const packageList = Array.isArray(packages) ? packages : [packages];
|
||||
const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList), { stdio: "inherit" });
|
||||
const error = npmProcess.error;
|
||||
|
||||
if (error && error.code === "ENOENT") {
|
||||
const pluralS = packageList.length > 1 ? "s" : "";
|
||||
|
||||
log.error(`Could not execute npm. Please install the following package${pluralS} with a package manager of your choice: ${packageList.join(", ")}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch `peerDependencies` of the given package by `npm show` command.
|
||||
* @param {string} packageName The package name to fetch peerDependencies.
|
||||
* @returns {Object} Gotten peerDependencies. Returns null if npm was not found.
|
||||
*/
|
||||
function fetchPeerDependencies(packageName) {
|
||||
const npmProcess = spawn.sync(
|
||||
"npm",
|
||||
["show", "--json", packageName, "peerDependencies"],
|
||||
{ encoding: "utf8" }
|
||||
);
|
||||
|
||||
const error = npmProcess.error;
|
||||
|
||||
if (error && error.code === "ENOENT") {
|
||||
return null;
|
||||
}
|
||||
const fetchedText = npmProcess.stdout.trim();
|
||||
|
||||
return JSON.parse(fetchedText || "{}");
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether node modules are include in a project's package.json.
|
||||
* @param {string[]} packages Array of node module names
|
||||
* @param {Object} opt Options Object
|
||||
* @param {boolean} opt.dependencies Set to true to check for direct dependencies
|
||||
* @param {boolean} opt.devDependencies Set to true to check for development dependencies
|
||||
* @param {boolean} opt.startdir Directory to begin searching from
|
||||
* @returns {Object} An object whose keys are the module names
|
||||
* and values are booleans indicating installation.
|
||||
*/
|
||||
function check(packages, opt) {
|
||||
const deps = new Set();
|
||||
const pkgJson = (opt) ? findPackageJson(opt.startDir) : findPackageJson();
|
||||
let fileJson;
|
||||
|
||||
if (!pkgJson) {
|
||||
throw new Error("Could not find a package.json file. Run 'npm init' to create one.");
|
||||
}
|
||||
|
||||
try {
|
||||
fileJson = JSON.parse(fs.readFileSync(pkgJson, "utf8"));
|
||||
} catch (e) {
|
||||
const error = new Error(e);
|
||||
|
||||
error.messageTemplate = "failed-to-read-json";
|
||||
error.messageData = {
|
||||
path: pkgJson,
|
||||
message: e.message
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
|
||||
["dependencies", "devDependencies"].forEach(key => {
|
||||
if (opt[key] && typeof fileJson[key] === "object") {
|
||||
Object.keys(fileJson[key]).forEach(dep => deps.add(dep));
|
||||
}
|
||||
});
|
||||
|
||||
return packages.reduce((status, pkg) => {
|
||||
status[pkg] = deps.has(pkg);
|
||||
return status;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether node modules are included in the dependencies of a project's
|
||||
* package.json.
|
||||
*
|
||||
* Convenience wrapper around check().
|
||||
* @param {string[]} packages Array of node modules to check.
|
||||
* @param {string} rootDir The directory containing a package.json
|
||||
* @returns {Object} An object whose keys are the module names
|
||||
* and values are booleans indicating installation.
|
||||
*/
|
||||
function checkDeps(packages, rootDir) {
|
||||
return check(packages, { dependencies: true, startDir: rootDir });
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether node modules are included in the devDependencies of a project's
|
||||
* package.json.
|
||||
*
|
||||
* Convenience wrapper around check().
|
||||
* @param {string[]} packages Array of node modules to check.
|
||||
* @returns {Object} An object whose keys are the module names
|
||||
* and values are booleans indicating installation.
|
||||
*/
|
||||
function checkDevDeps(packages) {
|
||||
return check(packages, { devDependencies: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether package.json is found in current path.
|
||||
* @param {string} [startDir] Starting directory
|
||||
* @returns {boolean} Whether a package.json is found in current path.
|
||||
*/
|
||||
function checkPackageJson(startDir) {
|
||||
return !!findPackageJson(startDir);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
installSyncSaveDev,
|
||||
fetchPeerDependencies,
|
||||
findPackageJson,
|
||||
checkDeps,
|
||||
checkDevDeps,
|
||||
checkPackageJson
|
||||
};
|
||||
109
node_modules/eslint/lib/init/source-code-utils.js
generated
vendored
109
node_modules/eslint/lib/init/source-code-utils.js
generated
vendored
|
|
@ -1,109 +0,0 @@
|
|||
/**
|
||||
* @fileoverview Tools for obtaining SourceCode objects.
|
||||
* @author Ian VanSchooten
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const { CLIEngine } = require("../cli-engine");
|
||||
|
||||
/*
|
||||
* This is used for:
|
||||
*
|
||||
* 1. Enumerate target file because we have not expose such a API on `CLIEngine`
|
||||
* (https://github.com/eslint/eslint/issues/11222).
|
||||
* 2. Create `SourceCode` instances. Because we don't have any function which
|
||||
* instantiate `SourceCode` so it needs to take the created `SourceCode`
|
||||
* instance out after linting.
|
||||
*
|
||||
* TODO1: Expose the API that enumerates target files.
|
||||
* TODO2: Extract the creation logic of `SourceCode` from `Linter` class.
|
||||
*/
|
||||
const { getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); // eslint-disable-line node/no-restricted-require
|
||||
|
||||
const debug = require("debug")("eslint:source-code-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get the SourceCode object for a single file
|
||||
* @param {string} filename The fully resolved filename to get SourceCode from.
|
||||
* @param {Object} engine A CLIEngine.
|
||||
* @returns {Array} Array of the SourceCode object representing the file
|
||||
* and fatal error message.
|
||||
*/
|
||||
function getSourceCodeOfFile(filename, engine) {
|
||||
debug("getting sourceCode of", filename);
|
||||
const results = engine.executeOnFiles([filename]);
|
||||
|
||||
if (results && results.results[0] && results.results[0].messages[0] && results.results[0].messages[0].fatal) {
|
||||
const msg = results.results[0].messages[0];
|
||||
|
||||
throw new Error(`(${filename}:${msg.line}:${msg.column}) ${msg.message}`);
|
||||
}
|
||||
|
||||
// TODO: extract the logic that creates source code objects to `SourceCode#parse(text, options)` or something like.
|
||||
const { linter } = getCLIEngineInternalSlots(engine);
|
||||
const sourceCode = linter.getSourceCode();
|
||||
|
||||
return sourceCode;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* This callback is used to measure execution status in a progress bar
|
||||
* @callback progressCallback
|
||||
* @param {number} The total number of times the callback will be called.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the SourceCode of a single file, or set of files.
|
||||
* @param {string[]|string} patterns A filename, directory name, or glob, or an array of them
|
||||
* @param {Object} options A CLIEngine options object. If not provided, the default cli options will be used.
|
||||
* @param {progressCallback} callback Callback for reporting execution status
|
||||
* @returns {Object} The SourceCode of all processed files.
|
||||
*/
|
||||
function getSourceCodeOfFiles(patterns, options, callback) {
|
||||
const sourceCodes = {};
|
||||
const globPatternsList = typeof patterns === "string" ? [patterns] : patterns;
|
||||
const engine = new CLIEngine({ ...options, rules: {} });
|
||||
|
||||
// TODO: make file iteration as a public API and use it.
|
||||
const { fileEnumerator } = getCLIEngineInternalSlots(engine);
|
||||
const filenames =
|
||||
Array.from(fileEnumerator.iterateFiles(globPatternsList))
|
||||
.filter(entry => !entry.ignored)
|
||||
.map(entry => entry.filePath);
|
||||
|
||||
if (filenames.length === 0) {
|
||||
debug(`Did not find any files matching pattern(s): ${globPatternsList}`);
|
||||
}
|
||||
|
||||
filenames.forEach(filename => {
|
||||
const sourceCode = getSourceCodeOfFile(filename, engine);
|
||||
|
||||
if (sourceCode) {
|
||||
debug("got sourceCode of", filename);
|
||||
sourceCodes[filename] = sourceCode;
|
||||
}
|
||||
if (callback) {
|
||||
callback(filenames.length); // eslint-disable-line node/callback-return
|
||||
}
|
||||
});
|
||||
|
||||
return sourceCodes;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSourceCodeOfFiles
|
||||
};
|
||||
302
node_modules/eslint/lib/linter/apply-disable-directives.js
generated
vendored
302
node_modules/eslint/lib/linter/apply-disable-directives.js
generated
vendored
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const escapeRegExp = require("escape-string-regexp");
|
||||
|
||||
/**
|
||||
* Compares the locations of two objects in a source file
|
||||
* @param {{line: number, column: number}} itemA The first object
|
||||
|
|
@ -16,6 +18,177 @@ function compareLocations(itemA, itemB) {
|
|||
return itemA.line - itemB.line || itemA.column - itemB.column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups a set of directives into sub-arrays by their parent comment.
|
||||
* @param {Directive[]} directives Unused directives to be removed.
|
||||
* @returns {Directive[][]} Directives grouped by their parent comment.
|
||||
*/
|
||||
function groupByParentComment(directives) {
|
||||
const groups = new Map();
|
||||
|
||||
for (const directive of directives) {
|
||||
const { unprocessedDirective: { parentComment } } = directive;
|
||||
|
||||
if (groups.has(parentComment)) {
|
||||
groups.get(parentComment).push(directive);
|
||||
} else {
|
||||
groups.set(parentComment, [directive]);
|
||||
}
|
||||
}
|
||||
|
||||
return [...groups.values()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates removal details for a set of directives within the same comment.
|
||||
* @param {Directive[]} directives Unused directives to be removed.
|
||||
* @param {Token} commentToken The backing Comment token.
|
||||
* @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems.
|
||||
*/
|
||||
function createIndividualDirectivesRemoval(directives, commentToken) {
|
||||
|
||||
/*
|
||||
* `commentToken.value` starts right after `//` or `/*`.
|
||||
* All calculated offsets will be relative to this index.
|
||||
*/
|
||||
const commentValueStart = commentToken.range[0] + "//".length;
|
||||
|
||||
// Find where the list of rules starts. `\S+` matches with the directive name (e.g. `eslint-disable-line`)
|
||||
const listStartOffset = /^\s*\S+\s+/u.exec(commentToken.value)[0].length;
|
||||
|
||||
/*
|
||||
* Get the list text without any surrounding whitespace. In order to preserve the original
|
||||
* formatting, we don't want to change that whitespace.
|
||||
*
|
||||
* // eslint-disable-line rule-one , rule-two , rule-three -- comment
|
||||
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
*/
|
||||
const listText = commentToken.value
|
||||
.slice(listStartOffset) // remove directive name and all whitespace before the list
|
||||
.split(/\s-{2,}\s/u)[0] // remove `-- comment`, if it exists
|
||||
.trimEnd(); // remove all whitespace after the list
|
||||
|
||||
/*
|
||||
* We can assume that `listText` contains multiple elements.
|
||||
* Otherwise, this function wouldn't be called - if there is
|
||||
* only one rule in the list, then the whole comment must be removed.
|
||||
*/
|
||||
|
||||
return directives.map(directive => {
|
||||
const { ruleId } = directive;
|
||||
|
||||
const regex = new RegExp(String.raw`(?:^|\s*,\s*)${escapeRegExp(ruleId)}(?:\s*,\s*|$)`, "u");
|
||||
const match = regex.exec(listText);
|
||||
const matchedText = match[0];
|
||||
const matchStartOffset = listStartOffset + match.index;
|
||||
const matchEndOffset = matchStartOffset + matchedText.length;
|
||||
|
||||
const firstIndexOfComma = matchedText.indexOf(",");
|
||||
const lastIndexOfComma = matchedText.lastIndexOf(",");
|
||||
|
||||
let removalStartOffset, removalEndOffset;
|
||||
|
||||
if (firstIndexOfComma !== lastIndexOfComma) {
|
||||
|
||||
/*
|
||||
* Since there are two commas, this must one of the elements in the middle of the list.
|
||||
* Matched range starts where the previous rule name ends, and ends where the next rule name starts.
|
||||
*
|
||||
* // eslint-disable-line rule-one , rule-two , rule-three -- comment
|
||||
* ^^^^^^^^^^^^^^
|
||||
*
|
||||
* We want to remove only the content between the two commas, and also one of the commas.
|
||||
*
|
||||
* // eslint-disable-line rule-one , rule-two , rule-three -- comment
|
||||
* ^^^^^^^^^^^
|
||||
*/
|
||||
removalStartOffset = matchStartOffset + firstIndexOfComma;
|
||||
removalEndOffset = matchStartOffset + lastIndexOfComma;
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* This is either the first element or the last element.
|
||||
*
|
||||
* If this is the first element, matched range starts where the first rule name starts
|
||||
* and ends where the second rule name starts. This is exactly the range we want
|
||||
* to remove so that the second rule name will start where the first one was starting
|
||||
* and thus preserve the original formatting.
|
||||
*
|
||||
* // eslint-disable-line rule-one , rule-two , rule-three -- comment
|
||||
* ^^^^^^^^^^^
|
||||
*
|
||||
* Similarly, if this is the last element, we've already matched the range we want to
|
||||
* remove. The previous rule name will end where the last one was ending, relative
|
||||
* to the content on the right side.
|
||||
*
|
||||
* // eslint-disable-line rule-one , rule-two , rule-three -- comment
|
||||
* ^^^^^^^^^^^^^
|
||||
*/
|
||||
removalStartOffset = matchStartOffset;
|
||||
removalEndOffset = matchEndOffset;
|
||||
}
|
||||
|
||||
return {
|
||||
description: `'${ruleId}'`,
|
||||
fix: {
|
||||
range: [
|
||||
commentValueStart + removalStartOffset,
|
||||
commentValueStart + removalEndOffset
|
||||
],
|
||||
text: ""
|
||||
},
|
||||
unprocessedDirective: directive.unprocessedDirective
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a description of deleting an entire unused disable comment.
|
||||
* @param {Directive[]} directives Unused directives to be removed.
|
||||
* @param {Token} commentToken The backing Comment token.
|
||||
* @returns {{ description, fix, unprocessedDirective }} Details for later creation of an output Problem.
|
||||
*/
|
||||
function createCommentRemoval(directives, commentToken) {
|
||||
const { range } = commentToken;
|
||||
const ruleIds = directives.filter(directive => directive.ruleId).map(directive => `'${directive.ruleId}'`);
|
||||
|
||||
return {
|
||||
description: ruleIds.length <= 2
|
||||
? ruleIds.join(" or ")
|
||||
: `${ruleIds.slice(0, ruleIds.length - 1).join(", ")}, or ${ruleIds[ruleIds.length - 1]}`,
|
||||
fix: {
|
||||
range,
|
||||
text: " "
|
||||
},
|
||||
unprocessedDirective: directives[0].unprocessedDirective
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses details from directives to create output Problems.
|
||||
* @param {Directive[]} allDirectives Unused directives to be removed.
|
||||
* @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems.
|
||||
*/
|
||||
function processUnusedDisableDirectives(allDirectives) {
|
||||
const directiveGroups = groupByParentComment(allDirectives);
|
||||
|
||||
return directiveGroups.flatMap(
|
||||
directives => {
|
||||
const { parentComment } = directives[0].unprocessedDirective;
|
||||
const remainingRuleIds = new Set(parentComment.ruleIds);
|
||||
|
||||
for (const directive of directives) {
|
||||
remainingRuleIds.delete(directive.ruleId);
|
||||
}
|
||||
|
||||
return remainingRuleIds.size
|
||||
? createIndividualDirectivesRemoval(directives, parentComment.commentToken)
|
||||
: [createCommentRemoval(directives, parentComment.commentToken)];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the same as the exported function, except that it
|
||||
* doesn't handle disable-line and disable-next-line directives, and it always reports unused
|
||||
|
|
@ -24,119 +197,106 @@ function compareLocations(itemA, itemB) {
|
|||
* for the exported function, except that `reportUnusedDisableDirectives` is not supported
|
||||
* (this function always reports unused disable directives).
|
||||
* @returns {{problems: Problem[], unusedDisableDirectives: Problem[]}} An object with a list
|
||||
* of filtered problems and unused eslint-disable directives
|
||||
* of problems (including suppressed ones) and unused eslint-disable directives
|
||||
*/
|
||||
function applyDirectives(options) {
|
||||
const problems = [];
|
||||
let nextDirectiveIndex = 0;
|
||||
let currentGlobalDisableDirective = null;
|
||||
const disabledRuleMap = new Map();
|
||||
|
||||
// enabledRules is only used when there is a current global disable directive.
|
||||
const enabledRules = new Set();
|
||||
const usedDisableDirectives = new Set();
|
||||
|
||||
for (const problem of options.problems) {
|
||||
let disableDirectivesForProblem = [];
|
||||
let nextDirectiveIndex = 0;
|
||||
|
||||
while (
|
||||
nextDirectiveIndex < options.directives.length &&
|
||||
compareLocations(options.directives[nextDirectiveIndex], problem) <= 0
|
||||
) {
|
||||
const directive = options.directives[nextDirectiveIndex++];
|
||||
|
||||
switch (directive.type) {
|
||||
case "disable":
|
||||
if (directive.ruleId === null) {
|
||||
currentGlobalDisableDirective = directive;
|
||||
disabledRuleMap.clear();
|
||||
enabledRules.clear();
|
||||
} else if (currentGlobalDisableDirective) {
|
||||
enabledRules.delete(directive.ruleId);
|
||||
disabledRuleMap.set(directive.ruleId, directive);
|
||||
} else {
|
||||
disabledRuleMap.set(directive.ruleId, directive);
|
||||
}
|
||||
break;
|
||||
if (directive.ruleId === null || directive.ruleId === problem.ruleId) {
|
||||
switch (directive.type) {
|
||||
case "disable":
|
||||
disableDirectivesForProblem.push(directive);
|
||||
break;
|
||||
|
||||
case "enable":
|
||||
if (directive.ruleId === null) {
|
||||
currentGlobalDisableDirective = null;
|
||||
disabledRuleMap.clear();
|
||||
} else if (currentGlobalDisableDirective) {
|
||||
enabledRules.add(directive.ruleId);
|
||||
disabledRuleMap.delete(directive.ruleId);
|
||||
} else {
|
||||
disabledRuleMap.delete(directive.ruleId);
|
||||
}
|
||||
break;
|
||||
case "enable":
|
||||
disableDirectivesForProblem = [];
|
||||
break;
|
||||
|
||||
// no default
|
||||
// no default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (disabledRuleMap.has(problem.ruleId)) {
|
||||
usedDisableDirectives.add(disabledRuleMap.get(problem.ruleId));
|
||||
} else if (currentGlobalDisableDirective && !enabledRules.has(problem.ruleId)) {
|
||||
usedDisableDirectives.add(currentGlobalDisableDirective);
|
||||
} else {
|
||||
problems.push(problem);
|
||||
if (disableDirectivesForProblem.length > 0) {
|
||||
const suppressions = disableDirectivesForProblem.map(directive => ({
|
||||
kind: "directive",
|
||||
justification: directive.unprocessedDirective.justification
|
||||
}));
|
||||
|
||||
if (problem.suppressions) {
|
||||
problem.suppressions = problem.suppressions.concat(suppressions);
|
||||
} else {
|
||||
problem.suppressions = suppressions;
|
||||
usedDisableDirectives.add(disableDirectivesForProblem[disableDirectivesForProblem.length - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
problems.push(problem);
|
||||
}
|
||||
|
||||
const unusedDisableDirectives = options.directives
|
||||
.filter(directive => directive.type === "disable" && !usedDisableDirectives.has(directive))
|
||||
.map(directive => ({
|
||||
ruleId: null,
|
||||
message: directive.ruleId
|
||||
? `Unused eslint-disable directive (no problems were reported from '${directive.ruleId}').`
|
||||
: "Unused eslint-disable directive (no problems were reported).",
|
||||
line: directive.unprocessedDirective.line,
|
||||
column: directive.unprocessedDirective.column,
|
||||
severity: options.reportUnusedDisableDirectives === "warn" ? 1 : 2,
|
||||
nodeType: null
|
||||
}));
|
||||
const unusedDisableDirectivesToReport = options.directives
|
||||
.filter(directive => directive.type === "disable" && !usedDisableDirectives.has(directive));
|
||||
|
||||
const processed = processUnusedDisableDirectives(unusedDisableDirectivesToReport);
|
||||
|
||||
const unusedDisableDirectives = processed
|
||||
.map(({ description, fix, unprocessedDirective }) => {
|
||||
const { parentComment, type, line, column } = unprocessedDirective;
|
||||
|
||||
return {
|
||||
ruleId: null,
|
||||
message: description
|
||||
? `Unused eslint-disable directive (no problems were reported from ${description}).`
|
||||
: "Unused eslint-disable directive (no problems were reported).",
|
||||
line: type === "disable-next-line" ? parentComment.commentToken.loc.start.line : line,
|
||||
column: type === "disable-next-line" ? parentComment.commentToken.loc.start.column + 1 : column,
|
||||
severity: options.reportUnusedDisableDirectives === "warn" ? 1 : 2,
|
||||
nodeType: null,
|
||||
...options.disableFixes ? {} : { fix }
|
||||
};
|
||||
});
|
||||
|
||||
return { problems, unusedDisableDirectives };
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of directive comments (i.e. metadata about eslint-disable and eslint-enable comments) and a list
|
||||
* of reported problems, determines which problems should be reported.
|
||||
* of reported problems, adds the suppression information to the problems.
|
||||
* @param {Object} options Information about directives and problems
|
||||
* @param {{
|
||||
* type: ("disable"|"enable"|"disable-line"|"disable-next-line"),
|
||||
* ruleId: (string|null),
|
||||
* line: number,
|
||||
* column: number
|
||||
* column: number,
|
||||
* justification: string
|
||||
* }} options.directives Directive comments found in the file, with one-based columns.
|
||||
* Two directive comments can only have the same location if they also have the same type (e.g. a single eslint-disable
|
||||
* comment for two different rules is represented as two directives).
|
||||
* @param {{ruleId: (string|null), line: number, column: number}[]} options.problems
|
||||
* A list of problems reported by rules, sorted by increasing location in the file, with one-based columns.
|
||||
* @param {"off" | "warn" | "error"} options.reportUnusedDisableDirectives If `"warn"` or `"error"`, adds additional problems for unused directives
|
||||
* @returns {{ruleId: (string|null), line: number, column: number}[]}
|
||||
* A list of reported problems that were not disabled by the directive comments.
|
||||
* @param {boolean} options.disableFixes If true, it doesn't make `fix` properties.
|
||||
* @returns {{ruleId: (string|null), line: number, column: number, suppressions?: {kind: string, justification: string}}[]}
|
||||
* An object with a list of reported problems, the suppressed of which contain the suppression information.
|
||||
*/
|
||||
module.exports = ({ directives, problems, reportUnusedDisableDirectives = "off" }) => {
|
||||
module.exports = ({ directives, disableFixes, problems, reportUnusedDisableDirectives = "off" }) => {
|
||||
const blockDirectives = directives
|
||||
.filter(directive => directive.type === "disable" || directive.type === "enable")
|
||||
.map(directive => Object.assign({}, directive, { unprocessedDirective: directive }))
|
||||
.sort(compareLocations);
|
||||
|
||||
/**
|
||||
* Returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level.
|
||||
* TODO(stephenwade): Replace this with array.flatMap when we drop support for Node v10
|
||||
* @param {any[]} array The array to process
|
||||
* @param {Function} fn The function to use
|
||||
* @returns {any[]} The result array
|
||||
*/
|
||||
function flatMap(array, fn) {
|
||||
const mapped = array.map(fn);
|
||||
const flattened = [].concat(...mapped);
|
||||
|
||||
return flattened;
|
||||
}
|
||||
|
||||
const lineDirectives = flatMap(directives, directive => {
|
||||
const lineDirectives = directives.flatMap(directive => {
|
||||
switch (directive.type) {
|
||||
case "disable":
|
||||
case "enable":
|
||||
|
|
@ -162,11 +322,13 @@ module.exports = ({ directives, problems, reportUnusedDisableDirectives = "off"
|
|||
const blockDirectivesResult = applyDirectives({
|
||||
problems,
|
||||
directives: blockDirectives,
|
||||
disableFixes,
|
||||
reportUnusedDisableDirectives
|
||||
});
|
||||
const lineDirectivesResult = applyDirectives({
|
||||
problems: blockDirectivesResult.problems,
|
||||
directives: lineDirectives,
|
||||
disableFixes,
|
||||
reportUnusedDisableDirectives
|
||||
});
|
||||
|
||||
|
|
|
|||
156
node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js
generated
vendored
156
node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js
generated
vendored
|
|
@ -29,6 +29,18 @@ function isCaseNode(node) {
|
|||
return Boolean(node.test);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given node appears as the value of a PropertyDefinition node.
|
||||
* @param {ASTNode} node THe node to check.
|
||||
* @returns {boolean} `true` if the node is a PropertyDefinition value,
|
||||
* false if not.
|
||||
*/
|
||||
function isPropertyDefinitionValue(node) {
|
||||
const parent = node.parent;
|
||||
|
||||
return parent && parent.type === "PropertyDefinition" && parent.value === node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given logical operator is taken into account for the code
|
||||
* path analysis.
|
||||
|
|
@ -138,6 +150,7 @@ function isIdentifierReference(node) {
|
|||
return parent.id !== node;
|
||||
|
||||
case "Property":
|
||||
case "PropertyDefinition":
|
||||
case "MethodDefinition":
|
||||
return (
|
||||
parent.key !== node ||
|
||||
|
|
@ -388,29 +401,68 @@ function processCodePathToEnter(analyzer, node) {
|
|||
let state = codePath && CodePath.getState(codePath);
|
||||
const parent = node.parent;
|
||||
|
||||
/**
|
||||
* Creates a new code path and trigger the onCodePathStart event
|
||||
* based on the currently selected node.
|
||||
* @param {string} origin The reason the code path was started.
|
||||
* @returns {void}
|
||||
*/
|
||||
function startCodePath(origin) {
|
||||
if (codePath) {
|
||||
|
||||
// Emits onCodePathSegmentStart events if updated.
|
||||
forwardCurrentToHead(analyzer, node);
|
||||
debug.dumpState(node, state, false);
|
||||
}
|
||||
|
||||
// Create the code path of this scope.
|
||||
codePath = analyzer.codePath = new CodePath({
|
||||
id: analyzer.idGenerator.next(),
|
||||
origin,
|
||||
upper: codePath,
|
||||
onLooped: analyzer.onLooped
|
||||
});
|
||||
state = CodePath.getState(codePath);
|
||||
|
||||
// Emits onCodePathStart events.
|
||||
debug.dump(`onCodePathStart ${codePath.id}`);
|
||||
analyzer.emitter.emit("onCodePathStart", codePath, node);
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case: The right side of class field initializer is considered
|
||||
* to be its own function, so we need to start a new code path in this
|
||||
* case.
|
||||
*/
|
||||
if (isPropertyDefinitionValue(node)) {
|
||||
startCodePath("class-field-initializer");
|
||||
|
||||
/*
|
||||
* Intentional fall through because `node` needs to also be
|
||||
* processed by the code below. For example, if we have:
|
||||
*
|
||||
* class Foo {
|
||||
* a = () => {}
|
||||
* }
|
||||
*
|
||||
* In this case, we also need start a second code path.
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
switch (node.type) {
|
||||
case "Program":
|
||||
startCodePath("program");
|
||||
break;
|
||||
|
||||
case "FunctionDeclaration":
|
||||
case "FunctionExpression":
|
||||
case "ArrowFunctionExpression":
|
||||
if (codePath) {
|
||||
startCodePath("function");
|
||||
break;
|
||||
|
||||
// Emits onCodePathSegmentStart events if updated.
|
||||
forwardCurrentToHead(analyzer, node);
|
||||
debug.dumpState(node, state, false);
|
||||
}
|
||||
|
||||
// Create the code path of this scope.
|
||||
codePath = analyzer.codePath = new CodePath(
|
||||
analyzer.idGenerator.next(),
|
||||
codePath,
|
||||
analyzer.onLooped
|
||||
);
|
||||
state = CodePath.getState(codePath);
|
||||
|
||||
// Emits onCodePathStart events.
|
||||
debug.dump(`onCodePathStart ${codePath.id}`);
|
||||
analyzer.emitter.emit("onCodePathStart", codePath, node);
|
||||
case "StaticBlock":
|
||||
startCodePath("class-static-block");
|
||||
break;
|
||||
|
||||
case "ChainExpression":
|
||||
|
|
@ -503,6 +555,7 @@ function processCodePathToEnter(analyzer, node) {
|
|||
* @returns {void}
|
||||
*/
|
||||
function processCodePathToExit(analyzer, node) {
|
||||
|
||||
const codePath = analyzer.codePath;
|
||||
const state = CodePath.getState(codePath);
|
||||
let dontForward = false;
|
||||
|
|
@ -627,28 +680,39 @@ function processCodePathToExit(analyzer, node) {
|
|||
* @returns {void}
|
||||
*/
|
||||
function postprocess(analyzer, node) {
|
||||
|
||||
/**
|
||||
* Ends the code path for the current node.
|
||||
* @returns {void}
|
||||
*/
|
||||
function endCodePath() {
|
||||
let codePath = analyzer.codePath;
|
||||
|
||||
// Mark the current path as the final node.
|
||||
CodePath.getState(codePath).makeFinal();
|
||||
|
||||
// Emits onCodePathSegmentEnd event of the current segments.
|
||||
leaveFromCurrentSegment(analyzer, node);
|
||||
|
||||
// Emits onCodePathEnd event of this code path.
|
||||
debug.dump(`onCodePathEnd ${codePath.id}`);
|
||||
analyzer.emitter.emit("onCodePathEnd", codePath, node);
|
||||
debug.dumpDot(codePath);
|
||||
|
||||
codePath = analyzer.codePath = analyzer.codePath.upper;
|
||||
if (codePath) {
|
||||
debug.dumpState(node, CodePath.getState(codePath), true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch (node.type) {
|
||||
case "Program":
|
||||
case "FunctionDeclaration":
|
||||
case "FunctionExpression":
|
||||
case "ArrowFunctionExpression": {
|
||||
let codePath = analyzer.codePath;
|
||||
|
||||
// Mark the current path as the final node.
|
||||
CodePath.getState(codePath).makeFinal();
|
||||
|
||||
// Emits onCodePathSegmentEnd event of the current segments.
|
||||
leaveFromCurrentSegment(analyzer, node);
|
||||
|
||||
// Emits onCodePathEnd event of this code path.
|
||||
debug.dump(`onCodePathEnd ${codePath.id}`);
|
||||
analyzer.emitter.emit("onCodePathEnd", codePath, node);
|
||||
debug.dumpDot(codePath);
|
||||
|
||||
codePath = analyzer.codePath = analyzer.codePath.upper;
|
||||
if (codePath) {
|
||||
debug.dumpState(node, CodePath.getState(codePath), true);
|
||||
}
|
||||
case "ArrowFunctionExpression":
|
||||
case "StaticBlock": {
|
||||
endCodePath();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -662,6 +726,27 @@ function postprocess(analyzer, node) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case: The right side of class field initializer is considered
|
||||
* to be its own function, so we need to end a code path in this
|
||||
* case.
|
||||
*
|
||||
* We need to check after the other checks in order to close the
|
||||
* code paths in the correct order for code like this:
|
||||
*
|
||||
*
|
||||
* class Foo {
|
||||
* a = () => {}
|
||||
* }
|
||||
*
|
||||
* In this case, The ArrowFunctionExpression code path is closed first
|
||||
* and then we need to close the code path for the PropertyDefinition
|
||||
* value.
|
||||
*/
|
||||
if (isPropertyDefinitionValue(node)) {
|
||||
endCodePath();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -674,7 +759,6 @@ function postprocess(analyzer, node) {
|
|||
*/
|
||||
class CodePathAnalyzer {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {EventGenerator} eventGenerator An event generator to wrap.
|
||||
*/
|
||||
|
|
|
|||
7
node_modules/eslint/lib/linter/code-path-analysis/code-path-segment.js
generated
vendored
7
node_modules/eslint/lib/linter/code-path-analysis/code-path-segment.js
generated
vendored
|
|
@ -33,7 +33,6 @@ function isReachable(segment) {
|
|||
*/
|
||||
class CodePathSegment {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {string} id An identifier.
|
||||
* @param {CodePathSegment[]} allPrevSegments An array of the previous segments.
|
||||
|
|
@ -89,10 +88,10 @@ class CodePathSegment {
|
|||
}
|
||||
});
|
||||
|
||||
/* istanbul ignore if */
|
||||
/* c8 ignore start */
|
||||
if (debug.enabled) {
|
||||
this.internal.nodes = [];
|
||||
}
|
||||
}/* c8 ignore stop */
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -101,7 +100,7 @@ class CodePathSegment {
|
|||
* @returns {boolean} `true` if the segment is coming from the end of a loop.
|
||||
*/
|
||||
isLoopedPrevSegment(segment) {
|
||||
return this.internal.loopedPrevSegments.indexOf(segment) !== -1;
|
||||
return this.internal.loopedPrevSegments.includes(segment);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
21
node_modules/eslint/lib/linter/code-path-analysis/code-path-state.js
generated
vendored
21
node_modules/eslint/lib/linter/code-path-analysis/code-path-state.js
generated
vendored
|
|
@ -33,7 +33,7 @@ function addToReturnedOrThrown(dest, others, all, segments) {
|
|||
const segment = segments[i];
|
||||
|
||||
dest.push(segment);
|
||||
if (others.indexOf(segment) === -1) {
|
||||
if (!others.includes(segment)) {
|
||||
all.push(segment);
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ function getContinueContext(state, label) {
|
|||
context = context.upper;
|
||||
}
|
||||
|
||||
/* istanbul ignore next: foolproof (syntax error) */
|
||||
/* c8 ignore next */
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ function getBreakContext(state, label) {
|
|||
context = context.upper;
|
||||
}
|
||||
|
||||
/* istanbul ignore next: foolproof (syntax error) */
|
||||
/* c8 ignore next */
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +219,6 @@ function finalizeTestSegmentsOfFor(context, choiceContext, head) {
|
|||
*/
|
||||
class CodePathState {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {IdGenerator} idGenerator An id generator to generate id for code
|
||||
* path segments.
|
||||
|
|
@ -360,6 +359,7 @@ class CodePathState {
|
|||
|
||||
/**
|
||||
* Pops the last choice context and finalizes it.
|
||||
* @throws {Error} (Unreachable.)
|
||||
* @returns {ChoiceContext} The popped context.
|
||||
*/
|
||||
popChoiceContext() {
|
||||
|
|
@ -433,7 +433,7 @@ class CodePathState {
|
|||
*/
|
||||
return context;
|
||||
|
||||
/* istanbul ignore next */
|
||||
/* c8 ignore next */
|
||||
default:
|
||||
throw new Error("unreachable");
|
||||
}
|
||||
|
|
@ -450,6 +450,7 @@ class CodePathState {
|
|||
/**
|
||||
* Makes a code path segment of the right-hand operand of a logical
|
||||
* expression.
|
||||
* @throws {Error} (Unreachable.)
|
||||
* @returns {void}
|
||||
*/
|
||||
makeLogicalRight() {
|
||||
|
|
@ -965,6 +966,7 @@ class CodePathState {
|
|||
* `WhileStatement`, `DoWhileStatement`, `ForStatement`, `ForInStatement`,
|
||||
* and `ForStatement`.
|
||||
* @param {string|null} label A label of the node which was triggered.
|
||||
* @throws {Error} (Unreachable - unknown type.)
|
||||
* @returns {void}
|
||||
*/
|
||||
pushLoopContext(type, label) {
|
||||
|
|
@ -1028,7 +1030,7 @@ class CodePathState {
|
|||
};
|
||||
break;
|
||||
|
||||
/* istanbul ignore next */
|
||||
/* c8 ignore next */
|
||||
default:
|
||||
throw new Error(`unknown type: "${type}"`);
|
||||
}
|
||||
|
|
@ -1036,6 +1038,7 @@ class CodePathState {
|
|||
|
||||
/**
|
||||
* Pops the last context of a loop statement and finalizes it.
|
||||
* @throws {Error} (Unreachable - unknown type.)
|
||||
* @returns {void}
|
||||
*/
|
||||
popLoopContext() {
|
||||
|
|
@ -1092,7 +1095,7 @@ class CodePathState {
|
|||
);
|
||||
break;
|
||||
|
||||
/* istanbul ignore next */
|
||||
/* c8 ignore next */
|
||||
default:
|
||||
throw new Error("unreachable");
|
||||
}
|
||||
|
|
@ -1389,11 +1392,12 @@ class CodePathState {
|
|||
|
||||
const context = getBreakContext(this, label);
|
||||
|
||||
/* istanbul ignore else: foolproof (syntax error) */
|
||||
|
||||
if (context) {
|
||||
context.brokenForkContext.add(forkContext.head);
|
||||
}
|
||||
|
||||
/* c8 ignore next */
|
||||
forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
|
||||
}
|
||||
|
||||
|
|
@ -1414,7 +1418,6 @@ class CodePathState {
|
|||
|
||||
const context = getContinueContext(this, label);
|
||||
|
||||
/* istanbul ignore else: foolproof (syntax error) */
|
||||
if (context) {
|
||||
if (context.continueDestSegments) {
|
||||
makeLooped(this, forkContext.head, context.continueDestSegments);
|
||||
|
|
|
|||
21
node_modules/eslint/lib/linter/code-path-analysis/code-path.js
generated
vendored
21
node_modules/eslint/lib/linter/code-path-analysis/code-path.js
generated
vendored
|
|
@ -21,13 +21,15 @@ const IdGenerator = require("./id-generator");
|
|||
*/
|
||||
class CodePath {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {string} id An identifier.
|
||||
* @param {CodePath|null} upper The code path of the upper function scope.
|
||||
* @param {Function} onLooped A callback function to notify looping.
|
||||
* Creates a new instance.
|
||||
* @param {Object} options Options for the function (see below).
|
||||
* @param {string} options.id An identifier.
|
||||
* @param {string} options.origin The type of code path origin.
|
||||
* @param {CodePath|null} options.upper The code path of the upper function scope.
|
||||
* @param {Function} options.onLooped A callback function to notify looping.
|
||||
*/
|
||||
constructor(id, upper, onLooped) {
|
||||
constructor({ id, origin, upper, onLooped }) {
|
||||
|
||||
/**
|
||||
* The identifier of this code path.
|
||||
|
|
@ -36,6 +38,13 @@ class CodePath {
|
|||
*/
|
||||
this.id = id;
|
||||
|
||||
/**
|
||||
* The reason that this code path was started. May be "program",
|
||||
* "function", "class-field-initializer", or "class-static-block".
|
||||
* @type {string}
|
||||
*/
|
||||
this.origin = origin;
|
||||
|
||||
/**
|
||||
* The code path of the upper function scope.
|
||||
* @type {CodePath|null}
|
||||
|
|
@ -203,7 +212,7 @@ class CodePath {
|
|||
}
|
||||
|
||||
// Reset the flag of skipping if all branches have been skipped.
|
||||
if (skippedSegment && segment.prevSegments.indexOf(skippedSegment) !== -1) {
|
||||
if (skippedSegment && segment.prevSegments.includes(skippedSegment)) {
|
||||
skippedSegment = null;
|
||||
}
|
||||
visited[segment.id] = true;
|
||||
|
|
|
|||
10
node_modules/eslint/lib/linter/code-path-analysis/debug-helpers.js
generated
vendored
10
node_modules/eslint/lib/linter/code-path-analysis/debug-helpers.js
generated
vendored
|
|
@ -20,8 +20,8 @@ const debug = require("debug")("eslint:code-path");
|
|||
* @param {CodePathSegment} segment A segment to get.
|
||||
* @returns {string} Id of the segment.
|
||||
*/
|
||||
/* istanbul ignore next */
|
||||
function getId(segment) { // eslint-disable-line jsdoc/require-jsdoc
|
||||
/* c8 ignore next */
|
||||
function getId(segment) { // eslint-disable-line jsdoc/require-jsdoc -- Ignoring
|
||||
return segment.id + (segment.reachable ? "" : "!");
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ module.exports = {
|
|||
* @param {boolean} leaving A flag whether or not it's leaving
|
||||
* @returns {void}
|
||||
*/
|
||||
dumpState: !debug.enabled ? debug : /* istanbul ignore next */ function(node, state, leaving) {
|
||||
dumpState: !debug.enabled ? debug : /* c8 ignore next */ function(node, state, leaving) {
|
||||
for (let i = 0; i < state.currentSegments.length; ++i) {
|
||||
const segInternal = state.currentSegments[i].internal;
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ module.exports = {
|
|||
* @see http://www.graphviz.org
|
||||
* @see http://www.webgraphviz.com
|
||||
*/
|
||||
dumpDot: !debug.enabled ? debug : /* istanbul ignore next */ function(codePath) {
|
||||
dumpDot: !debug.enabled ? debug : /* c8 ignore next */ function(codePath) {
|
||||
let text =
|
||||
"\n" +
|
||||
"digraph {\n" +
|
||||
|
|
@ -115,7 +115,7 @@ module.exports = {
|
|||
const traceMap = Object.create(null);
|
||||
const arrows = this.makeDotArrows(codePath, traceMap);
|
||||
|
||||
for (const id in traceMap) { // eslint-disable-line guard-for-in
|
||||
for (const id in traceMap) { // eslint-disable-line guard-for-in -- Want ability to traverse prototype
|
||||
const segment = traceMap[id];
|
||||
|
||||
text += `${id}[`;
|
||||
|
|
|
|||
1
node_modules/eslint/lib/linter/code-path-analysis/fork-context.js
generated
vendored
1
node_modules/eslint/lib/linter/code-path-analysis/fork-context.js
generated
vendored
|
|
@ -97,7 +97,6 @@ function mergeExtraSegments(context, segments) {
|
|||
*/
|
||||
class ForkContext {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {IdGenerator} idGenerator An identifier generator for segments.
|
||||
* @param {ForkContext|null} upper An upper fork context.
|
||||
|
|
|
|||
5
node_modules/eslint/lib/linter/code-path-analysis/id-generator.js
generated
vendored
5
node_modules/eslint/lib/linter/code-path-analysis/id-generator.js
generated
vendored
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
class IdGenerator {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {string} prefix Optional. A prefix of generated ids.
|
||||
*/
|
||||
|
|
@ -34,10 +33,10 @@ class IdGenerator {
|
|||
next() {
|
||||
this.n = 1 + this.n | 0;
|
||||
|
||||
/* istanbul ignore if */
|
||||
/* c8 ignore start */
|
||||
if (this.n < 0) {
|
||||
this.n = 1;
|
||||
}
|
||||
}/* c8 ignore stop */
|
||||
|
||||
return this.prefix + this.n;
|
||||
}
|
||||
|
|
|
|||
11
node_modules/eslint/lib/linter/config-comment-parser.js
generated
vendored
11
node_modules/eslint/lib/linter/config-comment-parser.js
generated
vendored
|
|
@ -3,7 +3,7 @@
|
|||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/* eslint-disable class-methods-use-this*/
|
||||
/* eslint class-methods-use-this: off -- Methods desired on instance */
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -11,7 +11,11 @@
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
const levn = require("levn"),
|
||||
ConfigOps = require("@eslint/eslintrc/lib/shared/config-ops");
|
||||
{
|
||||
Legacy: {
|
||||
ConfigOps
|
||||
}
|
||||
} = require("@eslint/eslintrc/universal");
|
||||
|
||||
const debug = require("debug")("eslint:config-comment-parser");
|
||||
|
||||
|
|
@ -127,8 +131,7 @@ module.exports = class ConfigCommentParser {
|
|||
|
||||
const items = {};
|
||||
|
||||
// Collapse whitespace around commas
|
||||
string.replace(/\s*,\s*/gu, ",").split(/,+/u).forEach(name => {
|
||||
string.split(",").forEach(name => {
|
||||
const trimmedName = name.trim();
|
||||
|
||||
if (trimmedName) {
|
||||
|
|
|
|||
793
node_modules/eslint/lib/linter/linter.js
generated
vendored
793
node_modules/eslint/lib/linter/linter.js
generated
vendored
File diff suppressed because it is too large
Load diff
12
node_modules/eslint/lib/linter/node-event-generator.js
generated
vendored
12
node_modules/eslint/lib/linter/node-event-generator.js
generated
vendored
|
|
@ -37,9 +37,7 @@ const esquery = require("esquery");
|
|||
* @returns {any[]} The union of the input arrays
|
||||
*/
|
||||
function union(...arrays) {
|
||||
|
||||
// TODO(stephenwade): Replace this with arrays.flat() when we drop support for Node v10
|
||||
return [...new Set([].concat(...arrays))];
|
||||
return [...new Set(arrays.flat())];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -100,6 +98,13 @@ function getPossibleTypes(parsedSelector) {
|
|||
case "adjacent":
|
||||
return getPossibleTypes(parsedSelector.right);
|
||||
|
||||
case "class":
|
||||
if (parsedSelector.name === "function") {
|
||||
return ["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
default:
|
||||
return null;
|
||||
|
||||
|
|
@ -239,7 +244,6 @@ function parseSelector(rawSelector) {
|
|||
*/
|
||||
class NodeEventGenerator {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {SafeEmitter} emitter
|
||||
* An SafeEmitter which is the destination of events. This emitter must already
|
||||
|
|
|
|||
24
node_modules/eslint/lib/linter/report-translator.js
generated
vendored
24
node_modules/eslint/lib/linter/report-translator.js
generated
vendored
|
|
@ -32,18 +32,18 @@ const interpolate = require("./interpolate");
|
|||
/**
|
||||
* Information about the report
|
||||
* @typedef {Object} ReportInfo
|
||||
* @property {string} ruleId
|
||||
* @property {(0|1|2)} severity
|
||||
* @property {(string|undefined)} message
|
||||
* @property {(string|undefined)} [messageId]
|
||||
* @property {number} line
|
||||
* @property {number} column
|
||||
* @property {(number|undefined)} [endLine]
|
||||
* @property {(number|undefined)} [endColumn]
|
||||
* @property {(string|null)} nodeType
|
||||
* @property {string} source
|
||||
* @property {({text: string, range: (number[]|null)}|null)} [fix]
|
||||
* @property {Array<{text: string, range: (number[]|null)}|null>} [suggestions]
|
||||
* @property {string} ruleId The rule ID
|
||||
* @property {(0|1|2)} severity Severity of the error
|
||||
* @property {(string|undefined)} message The message
|
||||
* @property {(string|undefined)} [messageId] The message ID
|
||||
* @property {number} line The line number
|
||||
* @property {number} column The column number
|
||||
* @property {(number|undefined)} [endLine] The ending line number
|
||||
* @property {(number|undefined)} [endColumn] The ending column number
|
||||
* @property {(string|null)} nodeType Type of node
|
||||
* @property {string} source Source text
|
||||
* @property {({text: string, range: (number[]|null)}|null)} [fix] The fix object
|
||||
* @property {Array<{text: string, range: (number[]|null)}|null>} [suggestions] Suggestion info
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
|
|||
3
node_modules/eslint/lib/linter/rules.js
generated
vendored
3
node_modules/eslint/lib/linter/rules.js
generated
vendored
|
|
@ -30,6 +30,9 @@ function normalizeRule(rule) {
|
|||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A storage for rules.
|
||||
*/
|
||||
class Rules {
|
||||
constructor() {
|
||||
this._rules = Object.create(null);
|
||||
|
|
|
|||
4
node_modules/eslint/lib/linter/safe-emitter.js
generated
vendored
4
node_modules/eslint/lib/linter/safe-emitter.js
generated
vendored
|
|
@ -12,8 +12,8 @@
|
|||
/**
|
||||
* An event emitter
|
||||
* @typedef {Object} SafeEmitter
|
||||
* @property {function(eventName: string, listenerFunc: Function): void} on Adds a listener for a given event name
|
||||
* @property {function(eventName: string, arg1?: any, arg2?: any, arg3?: any)} emit Emits an event with a given name.
|
||||
* @property {(eventName: string, listenerFunc: Function) => void} on Adds a listener for a given event name
|
||||
* @property {(eventName: string, arg1?: any, arg2?: any, arg3?: any) => void} emit Emits an event with a given name.
|
||||
* This calls all the listeners that were listening for that name, with `arg1`, `arg2`, and `arg3` as arguments.
|
||||
* @property {function(): string[]} eventNames Gets the list of event names that have registered listeners.
|
||||
*/
|
||||
|
|
|
|||
4
node_modules/eslint/lib/linter/source-code-fixer.js
generated
vendored
4
node_modules/eslint/lib/linter/source-code-fixer.js
generated
vendored
|
|
@ -80,8 +80,8 @@ SourceCodeFixer.applyFixes = function(sourceText, messages, shouldFix) {
|
|||
|
||||
/**
|
||||
* Try to use the 'fix' from a problem.
|
||||
* @param {Message} problem The message object to apply fixes from
|
||||
* @returns {boolean} Whether fix was successfully applied
|
||||
* @param {Message} problem The message object to apply fixes from
|
||||
* @returns {boolean} Whether fix was successfully applied
|
||||
*/
|
||||
function attemptFix(problem) {
|
||||
const fix = problem.fix;
|
||||
|
|
|
|||
15
node_modules/eslint/lib/linter/timing.js
generated
vendored
15
node_modules/eslint/lib/linter/timing.js
generated
vendored
|
|
@ -9,7 +9,7 @@
|
|||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* istanbul ignore next */
|
||||
/* c8 ignore next */
|
||||
/**
|
||||
* Align the string to left
|
||||
* @param {string} str string to evaluate
|
||||
|
|
@ -22,7 +22,7 @@ function alignLeft(str, len, ch) {
|
|||
return str + new Array(len - str.length + 1).join(ch || " ");
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
/* c8 ignore next */
|
||||
/**
|
||||
* Align the string to right
|
||||
* @param {string} str string to evaluate
|
||||
|
|
@ -64,7 +64,7 @@ function getListSize() {
|
|||
return TIMING_ENV_VAR_AS_INTEGER > 10 ? TIMING_ENV_VAR_AS_INTEGER : MINIMUM_SIZE;
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
/* c8 ignore next */
|
||||
/**
|
||||
* display the data
|
||||
* @param {Object} data Data object to be displayed
|
||||
|
|
@ -116,17 +116,17 @@ function display(data) {
|
|||
return ALIGN[index](":", width + extraAlignment, "-");
|
||||
}).join("|"));
|
||||
|
||||
console.log(table.join("\n")); // eslint-disable-line no-console
|
||||
console.log(table.join("\n")); // eslint-disable-line no-console -- Debugging function
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
/* c8 ignore next */
|
||||
module.exports = (function() {
|
||||
|
||||
const data = Object.create(null);
|
||||
|
||||
/**
|
||||
* Time the run
|
||||
* @param {*} key key from the data object
|
||||
* @param {any} key key from the data object
|
||||
* @param {Function} fn function to be called
|
||||
* @returns {Function} function to be executed
|
||||
* @private
|
||||
|
|
@ -138,10 +138,11 @@ module.exports = (function() {
|
|||
|
||||
return function(...args) {
|
||||
let t = process.hrtime();
|
||||
const result = fn(...args);
|
||||
|
||||
fn(...args);
|
||||
t = process.hrtime(t);
|
||||
data[key] += t[0] * 1e3 + t[1] / 1e6;
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
536
node_modules/eslint/lib/options.js
generated
vendored
536
node_modules/eslint/lib/options.js
generated
vendored
|
|
@ -32,7 +32,7 @@ const optionator = require("optionator");
|
|||
* @property {string[]} [ext] Specify JavaScript file extensions
|
||||
* @property {boolean} fix Automatically fix problems
|
||||
* @property {boolean} fixDryRun Automatically fix problems without saving the changes to the file system
|
||||
* @property {("problem" | "suggestion" | "layout")[]} [fixType] Specify the types of fixes to apply (problem, suggestion, layout)
|
||||
* @property {("directive" | "problem" | "suggestion" | "layout")[]} [fixType] Specify the types of fixes to apply (directive, problem, suggestion, layout)
|
||||
* @property {string} format Use a specific output format
|
||||
* @property {string[]} [global] Define global variables
|
||||
* @property {boolean} [help] Show help
|
||||
|
|
@ -50,7 +50,7 @@ const optionator = require("optionator");
|
|||
* @property {boolean | undefined} reportUnusedDisableDirectives Adds reported errors for unused eslint-disable directives
|
||||
* @property {string} [resolvePluginsRelativeTo] A folder where plugins should be resolved from, CWD by default
|
||||
* @property {Object} [rule] Specify rules
|
||||
* @property {string[]} [rulesdir] Use additional rules from this directory
|
||||
* @property {string[]} [rulesdir] Load additional rules from this directory. Deprecated: Use rules from plugins
|
||||
* @property {boolean} stdin Lint code provided on <STDIN>
|
||||
* @property {string} [stdinFilename] Specify filename to process STDIN as
|
||||
* @property {boolean} quiet Report errors only
|
||||
|
|
@ -63,261 +63,315 @@ const optionator = require("optionator");
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
// exports "parse(args)", "generateHelp()", and "generateHelpForOption(optionName)"
|
||||
module.exports = optionator({
|
||||
prepend: "eslint [options] file.js [file.js] [dir]",
|
||||
defaults: {
|
||||
concatRepeatedArrays: true,
|
||||
mergeRepeatedObjects: true
|
||||
},
|
||||
options: [
|
||||
{
|
||||
heading: "Basic configuration"
|
||||
},
|
||||
{
|
||||
|
||||
/**
|
||||
* Creates the CLI options for ESLint.
|
||||
* @param {boolean} usingFlatConfig Indicates if flat config is being used.
|
||||
* @returns {Object} The optionator instance.
|
||||
*/
|
||||
module.exports = function(usingFlatConfig) {
|
||||
|
||||
let lookupFlag;
|
||||
|
||||
if (usingFlatConfig) {
|
||||
lookupFlag = {
|
||||
option: "config-lookup",
|
||||
type: "Boolean",
|
||||
default: "true",
|
||||
description: "Disable look up for eslint.config.js"
|
||||
};
|
||||
} else {
|
||||
lookupFlag = {
|
||||
option: "eslintrc",
|
||||
type: "Boolean",
|
||||
default: "true",
|
||||
description: "Disable use of configuration from .eslintrc.*"
|
||||
},
|
||||
{
|
||||
option: "config",
|
||||
alias: "c",
|
||||
type: "path::String",
|
||||
description: "Use this configuration, overriding .eslintrc.* config options if present"
|
||||
},
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
let envFlag;
|
||||
|
||||
if (!usingFlatConfig) {
|
||||
envFlag = {
|
||||
option: "env",
|
||||
type: "[String]",
|
||||
description: "Specify environments"
|
||||
},
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
let extFlag;
|
||||
|
||||
if (!usingFlatConfig) {
|
||||
extFlag = {
|
||||
option: "ext",
|
||||
type: "[String]",
|
||||
description: "Specify JavaScript file extensions"
|
||||
},
|
||||
{
|
||||
option: "global",
|
||||
type: "[String]",
|
||||
description: "Define global variables"
|
||||
},
|
||||
{
|
||||
option: "parser",
|
||||
type: "String",
|
||||
description: "Specify the parser to be used"
|
||||
},
|
||||
{
|
||||
option: "parser-options",
|
||||
type: "Object",
|
||||
description: "Specify parser options"
|
||||
},
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
let resolvePluginsFlag;
|
||||
|
||||
if (!usingFlatConfig) {
|
||||
resolvePluginsFlag = {
|
||||
option: "resolve-plugins-relative-to",
|
||||
type: "path::String",
|
||||
description: "A folder where plugins should be resolved from, CWD by default"
|
||||
},
|
||||
{
|
||||
heading: "Specifying rules and plugins"
|
||||
},
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
let rulesDirFlag;
|
||||
|
||||
if (!usingFlatConfig) {
|
||||
rulesDirFlag = {
|
||||
option: "rulesdir",
|
||||
type: "[path::String]",
|
||||
description: "Use additional rules from this directory"
|
||||
},
|
||||
{
|
||||
option: "plugin",
|
||||
type: "[String]",
|
||||
description: "Specify plugins"
|
||||
},
|
||||
{
|
||||
option: "rule",
|
||||
type: "Object",
|
||||
description: "Specify rules"
|
||||
},
|
||||
{
|
||||
heading: "Fixing problems"
|
||||
},
|
||||
{
|
||||
option: "fix",
|
||||
type: "Boolean",
|
||||
default: false,
|
||||
description: "Automatically fix problems"
|
||||
},
|
||||
{
|
||||
option: "fix-dry-run",
|
||||
type: "Boolean",
|
||||
default: false,
|
||||
description: "Automatically fix problems without saving the changes to the file system"
|
||||
},
|
||||
{
|
||||
option: "fix-type",
|
||||
type: "Array",
|
||||
description: "Specify the types of fixes to apply (problem, suggestion, layout)"
|
||||
},
|
||||
{
|
||||
heading: "Ignoring files"
|
||||
},
|
||||
{
|
||||
description: "Load additional rules from this directory. Deprecated: Use rules from plugins"
|
||||
};
|
||||
}
|
||||
|
||||
let ignorePathFlag;
|
||||
|
||||
if (!usingFlatConfig) {
|
||||
ignorePathFlag = {
|
||||
option: "ignore-path",
|
||||
type: "path::String",
|
||||
description: "Specify path of ignore file"
|
||||
};
|
||||
}
|
||||
|
||||
return optionator({
|
||||
prepend: "eslint [options] file.js [file.js] [dir]",
|
||||
defaults: {
|
||||
concatRepeatedArrays: true,
|
||||
mergeRepeatedObjects: true
|
||||
},
|
||||
{
|
||||
option: "ignore",
|
||||
type: "Boolean",
|
||||
default: "true",
|
||||
description: "Disable use of ignore files and patterns"
|
||||
},
|
||||
{
|
||||
option: "ignore-pattern",
|
||||
type: "[String]",
|
||||
description: "Pattern of files to ignore (in addition to those in .eslintignore)",
|
||||
concatRepeatedArrays: [true, {
|
||||
oneValuePerFlag: true
|
||||
}]
|
||||
},
|
||||
{
|
||||
heading: "Using stdin"
|
||||
},
|
||||
{
|
||||
option: "stdin",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Lint code provided on <STDIN>"
|
||||
},
|
||||
{
|
||||
option: "stdin-filename",
|
||||
type: "String",
|
||||
description: "Specify filename to process STDIN as"
|
||||
},
|
||||
{
|
||||
heading: "Handling warnings"
|
||||
},
|
||||
{
|
||||
option: "quiet",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Report errors only"
|
||||
},
|
||||
{
|
||||
option: "max-warnings",
|
||||
type: "Int",
|
||||
default: "-1",
|
||||
description: "Number of warnings to trigger nonzero exit code"
|
||||
},
|
||||
{
|
||||
heading: "Output"
|
||||
},
|
||||
{
|
||||
option: "output-file",
|
||||
alias: "o",
|
||||
type: "path::String",
|
||||
description: "Specify file to write report to"
|
||||
},
|
||||
{
|
||||
option: "format",
|
||||
alias: "f",
|
||||
type: "String",
|
||||
default: "stylish",
|
||||
description: "Use a specific output format"
|
||||
},
|
||||
{
|
||||
option: "color",
|
||||
type: "Boolean",
|
||||
alias: "no-color",
|
||||
description: "Force enabling/disabling of color"
|
||||
},
|
||||
{
|
||||
heading: "Inline configuration comments"
|
||||
},
|
||||
{
|
||||
option: "inline-config",
|
||||
type: "Boolean",
|
||||
default: "true",
|
||||
description: "Prevent comments from changing config or rules"
|
||||
},
|
||||
{
|
||||
option: "report-unused-disable-directives",
|
||||
type: "Boolean",
|
||||
default: void 0,
|
||||
description: "Adds reported errors for unused eslint-disable directives"
|
||||
},
|
||||
{
|
||||
heading: "Caching"
|
||||
},
|
||||
{
|
||||
option: "cache",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Only check changed files"
|
||||
},
|
||||
{
|
||||
option: "cache-file",
|
||||
type: "path::String",
|
||||
default: ".eslintcache",
|
||||
description: "Path to the cache file. Deprecated: use --cache-location"
|
||||
},
|
||||
{
|
||||
option: "cache-location",
|
||||
type: "path::String",
|
||||
description: "Path to the cache file or directory"
|
||||
},
|
||||
{
|
||||
option: "cache-strategy",
|
||||
dependsOn: ["cache"],
|
||||
type: "String",
|
||||
default: "metadata",
|
||||
enum: ["metadata", "content"],
|
||||
description: "Strategy to use for detecting changed files in the cache"
|
||||
},
|
||||
{
|
||||
heading: "Miscellaneous"
|
||||
},
|
||||
{
|
||||
option: "init",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Run config initialization wizard"
|
||||
},
|
||||
{
|
||||
option: "env-info",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Output execution environment information"
|
||||
},
|
||||
{
|
||||
option: "error-on-unmatched-pattern",
|
||||
type: "Boolean",
|
||||
default: "true",
|
||||
description: "Prevent errors when pattern is unmatched"
|
||||
},
|
||||
{
|
||||
option: "exit-on-fatal-error",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Exit with exit code 2 in case of fatal error"
|
||||
},
|
||||
{
|
||||
option: "debug",
|
||||
type: "Boolean",
|
||||
default: false,
|
||||
description: "Output debugging information"
|
||||
},
|
||||
{
|
||||
option: "help",
|
||||
alias: "h",
|
||||
type: "Boolean",
|
||||
description: "Show help"
|
||||
},
|
||||
{
|
||||
option: "version",
|
||||
alias: "v",
|
||||
type: "Boolean",
|
||||
description: "Output the version number"
|
||||
},
|
||||
{
|
||||
option: "print-config",
|
||||
type: "path::String",
|
||||
description: "Print the configuration for the given file"
|
||||
}
|
||||
]
|
||||
});
|
||||
options: [
|
||||
{
|
||||
heading: "Basic configuration"
|
||||
},
|
||||
lookupFlag,
|
||||
{
|
||||
option: "config",
|
||||
alias: "c",
|
||||
type: "path::String",
|
||||
description: usingFlatConfig
|
||||
? "Use this configuration instead of eslint.config.js"
|
||||
: "Use this configuration, overriding .eslintrc.* config options if present"
|
||||
},
|
||||
envFlag,
|
||||
extFlag,
|
||||
{
|
||||
option: "global",
|
||||
type: "[String]",
|
||||
description: "Define global variables"
|
||||
},
|
||||
{
|
||||
option: "parser",
|
||||
type: "String",
|
||||
description: "Specify the parser to be used"
|
||||
},
|
||||
{
|
||||
option: "parser-options",
|
||||
type: "Object",
|
||||
description: "Specify parser options"
|
||||
},
|
||||
resolvePluginsFlag,
|
||||
{
|
||||
heading: "Specify Rules and Plugins"
|
||||
},
|
||||
{
|
||||
option: "plugin",
|
||||
type: "[String]",
|
||||
description: "Specify plugins"
|
||||
},
|
||||
{
|
||||
option: "rule",
|
||||
type: "Object",
|
||||
description: "Specify rules"
|
||||
},
|
||||
rulesDirFlag,
|
||||
{
|
||||
heading: "Fix Problems"
|
||||
},
|
||||
{
|
||||
option: "fix",
|
||||
type: "Boolean",
|
||||
default: false,
|
||||
description: "Automatically fix problems"
|
||||
},
|
||||
{
|
||||
option: "fix-dry-run",
|
||||
type: "Boolean",
|
||||
default: false,
|
||||
description: "Automatically fix problems without saving the changes to the file system"
|
||||
},
|
||||
{
|
||||
option: "fix-type",
|
||||
type: "Array",
|
||||
description: "Specify the types of fixes to apply (directive, problem, suggestion, layout)"
|
||||
},
|
||||
{
|
||||
heading: "Ignore Files"
|
||||
},
|
||||
ignorePathFlag,
|
||||
{
|
||||
option: "ignore",
|
||||
type: "Boolean",
|
||||
default: "true",
|
||||
description: "Disable use of ignore files and patterns"
|
||||
},
|
||||
{
|
||||
option: "ignore-pattern",
|
||||
type: "[String]",
|
||||
description: "Pattern of files to ignore (in addition to those in .eslintignore)",
|
||||
concatRepeatedArrays: [true, {
|
||||
oneValuePerFlag: true
|
||||
}]
|
||||
},
|
||||
{
|
||||
heading: "Use stdin"
|
||||
},
|
||||
{
|
||||
option: "stdin",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Lint code provided on <STDIN>"
|
||||
},
|
||||
{
|
||||
option: "stdin-filename",
|
||||
type: "String",
|
||||
description: "Specify filename to process STDIN as"
|
||||
},
|
||||
{
|
||||
heading: "Handle Warnings"
|
||||
},
|
||||
{
|
||||
option: "quiet",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Report errors only"
|
||||
},
|
||||
{
|
||||
option: "max-warnings",
|
||||
type: "Int",
|
||||
default: "-1",
|
||||
description: "Number of warnings to trigger nonzero exit code"
|
||||
},
|
||||
{
|
||||
heading: "Output"
|
||||
},
|
||||
{
|
||||
option: "output-file",
|
||||
alias: "o",
|
||||
type: "path::String",
|
||||
description: "Specify file to write report to"
|
||||
},
|
||||
{
|
||||
option: "format",
|
||||
alias: "f",
|
||||
type: "String",
|
||||
default: "stylish",
|
||||
description: "Use a specific output format"
|
||||
},
|
||||
{
|
||||
option: "color",
|
||||
type: "Boolean",
|
||||
alias: "no-color",
|
||||
description: "Force enabling/disabling of color"
|
||||
},
|
||||
{
|
||||
heading: "Inline configuration comments"
|
||||
},
|
||||
{
|
||||
option: "inline-config",
|
||||
type: "Boolean",
|
||||
default: "true",
|
||||
description: "Prevent comments from changing config or rules"
|
||||
},
|
||||
{
|
||||
option: "report-unused-disable-directives",
|
||||
type: "Boolean",
|
||||
default: void 0,
|
||||
description: "Adds reported errors for unused eslint-disable directives"
|
||||
},
|
||||
{
|
||||
heading: "Caching"
|
||||
},
|
||||
{
|
||||
option: "cache",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Only check changed files"
|
||||
},
|
||||
{
|
||||
option: "cache-file",
|
||||
type: "path::String",
|
||||
default: ".eslintcache",
|
||||
description: "Path to the cache file. Deprecated: use --cache-location"
|
||||
},
|
||||
{
|
||||
option: "cache-location",
|
||||
type: "path::String",
|
||||
description: "Path to the cache file or directory"
|
||||
},
|
||||
{
|
||||
option: "cache-strategy",
|
||||
dependsOn: ["cache"],
|
||||
type: "String",
|
||||
default: "metadata",
|
||||
enum: ["metadata", "content"],
|
||||
description: "Strategy to use for detecting changed files in the cache"
|
||||
},
|
||||
{
|
||||
heading: "Miscellaneous"
|
||||
},
|
||||
{
|
||||
option: "init",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Run config initialization wizard"
|
||||
},
|
||||
{
|
||||
option: "env-info",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Output execution environment information"
|
||||
},
|
||||
{
|
||||
option: "error-on-unmatched-pattern",
|
||||
type: "Boolean",
|
||||
default: "true",
|
||||
description: "Prevent errors when pattern is unmatched"
|
||||
},
|
||||
{
|
||||
option: "exit-on-fatal-error",
|
||||
type: "Boolean",
|
||||
default: "false",
|
||||
description: "Exit with exit code 2 in case of fatal error"
|
||||
},
|
||||
{
|
||||
option: "debug",
|
||||
type: "Boolean",
|
||||
default: false,
|
||||
description: "Output debugging information"
|
||||
},
|
||||
{
|
||||
option: "help",
|
||||
alias: "h",
|
||||
type: "Boolean",
|
||||
description: "Show help"
|
||||
},
|
||||
{
|
||||
option: "version",
|
||||
alias: "v",
|
||||
type: "Boolean",
|
||||
description: "Output the version number"
|
||||
},
|
||||
{
|
||||
option: "print-config",
|
||||
type: "path::String",
|
||||
description: "Print the configuration for the given file"
|
||||
}
|
||||
].filter(value => !!value)
|
||||
});
|
||||
};
|
||||
|
|
|
|||
1044
node_modules/eslint/lib/rule-tester/flat-rule-tester.js
generated
vendored
Normal file
1044
node_modules/eslint/lib/rule-tester/flat-rule-tester.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
141
node_modules/eslint/lib/rule-tester/rule-tester.js
generated
vendored
141
node_modules/eslint/lib/rule-tester/rule-tester.js
generated
vendored
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
/* global describe, it */
|
||||
/* globals describe, it -- Mocha globals */
|
||||
|
||||
/*
|
||||
* This is a wrapper around mocha to allow for DRY unittests for eslint
|
||||
|
|
@ -55,15 +55,19 @@ const ajv = require("../shared/ajv")({ strictDefaults: true });
|
|||
const espreePath = require.resolve("espree");
|
||||
const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
||||
|
||||
const { SourceCode } = require("../source-code");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Typedefs
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @typedef {import("../shared/types").Parser} Parser */
|
||||
|
||||
/* eslint-disable jsdoc/valid-types -- https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/4#issuecomment-778805577 */
|
||||
/**
|
||||
* A test case that is expected to pass lint.
|
||||
* @typedef {Object} ValidTestCase
|
||||
* @property {string} [name] Name for the test case.
|
||||
* @property {string} code Code for the test case.
|
||||
* @property {any[]} [options] Options for the test case.
|
||||
* @property {{ [name: string]: any }} [settings] Settings for the test case.
|
||||
|
|
@ -78,6 +82,7 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
|||
/**
|
||||
* A test case that is expected to fail lint.
|
||||
* @typedef {Object} InvalidTestCase
|
||||
* @property {string} [name] Name for the test case.
|
||||
* @property {string} code Code for the test case.
|
||||
* @property {number | Array<TestCaseError | string | RegExp>} errors Expected errors.
|
||||
* @property {string | null} [output] The expected code after autofixes are applied. If set to `null`, the test runner will assert that no autofix is suggested.
|
||||
|
|
@ -103,6 +108,7 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
|||
* @property {number} [endLine] The 1-based line number of the reported end location.
|
||||
* @property {number} [endColumn] The 1-based column number of the reported end location.
|
||||
*/
|
||||
/* eslint-enable jsdoc/valid-types -- https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/4#issuecomment-778805577 */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private Members
|
||||
|
|
@ -120,6 +126,7 @@ let defaultConfig = { rules: {} };
|
|||
* configuration
|
||||
*/
|
||||
const RuleTesterParameters = [
|
||||
"name",
|
||||
"code",
|
||||
"filename",
|
||||
"options",
|
||||
|
|
@ -209,8 +216,11 @@ function freezeDeeply(x) {
|
|||
* @returns {string} The sanitized text.
|
||||
*/
|
||||
function sanitize(text) {
|
||||
if (typeof text !== "string") {
|
||||
return "";
|
||||
}
|
||||
return text.replace(
|
||||
/[\u0000-\u0009\u000b-\u001a]/gu, // eslint-disable-line no-control-regex
|
||||
/[\u0000-\u0009\u000b-\u001a]/gu, // eslint-disable-line no-control-regex -- Escaping controls
|
||||
c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}`
|
||||
);
|
||||
}
|
||||
|
|
@ -284,6 +294,47 @@ function wrapParser(parser) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to replace `SourceCode.prototype.getComments`.
|
||||
* @returns {void}
|
||||
* @throws {Error} Deprecation message.
|
||||
*/
|
||||
function getCommentsDeprecation() {
|
||||
throw new Error(
|
||||
"`SourceCode#getComments()` is deprecated and will be removed in a future major version. Use `getCommentsBefore()`, `getCommentsAfter()`, and `getCommentsInside()` instead."
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a deprecation warning if function-style format is being used.
|
||||
* @param {string} ruleName Name of the rule.
|
||||
* @returns {void}
|
||||
*/
|
||||
function emitLegacyRuleAPIWarning(ruleName) {
|
||||
if (!emitLegacyRuleAPIWarning[`warned-${ruleName}`]) {
|
||||
emitLegacyRuleAPIWarning[`warned-${ruleName}`] = true;
|
||||
process.emitWarning(
|
||||
`"${ruleName}" rule is using the deprecated function-style format and will stop working in ESLint v9. Please use object-style format: https://eslint.org/docs/latest/extend/custom-rules`,
|
||||
"DeprecationWarning"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a deprecation warning if rule has options but is missing the "meta.schema" property
|
||||
* @param {string} ruleName Name of the rule.
|
||||
* @returns {void}
|
||||
*/
|
||||
function emitMissingSchemaWarning(ruleName) {
|
||||
if (!emitMissingSchemaWarning[`warned-${ruleName}`]) {
|
||||
emitMissingSchemaWarning[`warned-${ruleName}`] = true;
|
||||
process.emitWarning(
|
||||
`"${ruleName}" rule has options but is missing the "meta.schema" property and will stop working in ESLint v9. Please add a schema: https://eslint.org/docs/latest/extend/custom-rules#options-schemas`,
|
||||
"DeprecationWarning"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -298,6 +349,7 @@ const IT_ONLY = Symbol("itOnly");
|
|||
* @this {Mocha}
|
||||
* @param {string} text The description of the test case.
|
||||
* @param {Function} method The logic of the test case.
|
||||
* @throws {Error} Any error upon execution of `method`.
|
||||
* @returns {any} Returned value of `method`.
|
||||
*/
|
||||
function itDefaultHandler(text, method) {
|
||||
|
|
@ -322,6 +374,9 @@ function describeDefaultHandler(text, method) {
|
|||
return method.call(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocha test wrapper.
|
||||
*/
|
||||
class RuleTester {
|
||||
|
||||
/**
|
||||
|
|
@ -353,6 +408,7 @@ class RuleTester {
|
|||
/**
|
||||
* Set the configuration to use for all future tests
|
||||
* @param {Object} config the configuration to use.
|
||||
* @throws {TypeError} If non-object config.
|
||||
* @returns {void}
|
||||
*/
|
||||
static setDefaultConfig(config) {
|
||||
|
|
@ -437,7 +493,7 @@ class RuleTester {
|
|||
if (typeof this[DESCRIBE] === "function" || typeof this[IT] === "function") {
|
||||
throw new Error(
|
||||
"Set `RuleTester.itOnly` to use `only` with a custom test framework.\n" +
|
||||
"See https://eslint.org/docs/developer-guide/nodejs-api#customizing-ruletester for more."
|
||||
"See https://eslint.org/docs/latest/integrate/nodejs-api#customizing-ruletester for more."
|
||||
);
|
||||
}
|
||||
if (typeof it === "function") {
|
||||
|
|
@ -468,6 +524,8 @@ class RuleTester {
|
|||
* valid: (ValidTestCase | string)[],
|
||||
* invalid: InvalidTestCase[]
|
||||
* }} test The collection of tests to run.
|
||||
* @throws {TypeError|Error} If non-object `test`, or if a required
|
||||
* scenario of the given type is missing.
|
||||
* @returns {void}
|
||||
*/
|
||||
run(ruleName, rule, test) {
|
||||
|
|
@ -493,6 +551,9 @@ class RuleTester {
|
|||
].concat(scenarioErrors).join("\n"));
|
||||
}
|
||||
|
||||
if (typeof rule === "function") {
|
||||
emitLegacyRuleAPIWarning(ruleName);
|
||||
}
|
||||
|
||||
linter.defineRule(ruleName, Object.assign({}, rule, {
|
||||
|
||||
|
|
@ -511,6 +572,7 @@ class RuleTester {
|
|||
/**
|
||||
* Run the rule for the given item
|
||||
* @param {string|Object} item Item to run the rule against
|
||||
* @throws {Error} If an invalid schema.
|
||||
* @returns {Object} Eslint run result
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -549,6 +611,15 @@ class RuleTester {
|
|||
|
||||
if (hasOwnProperty(item, "options")) {
|
||||
assert(Array.isArray(item.options), "options must be an array");
|
||||
if (
|
||||
item.options.length > 0 &&
|
||||
typeof rule === "object" &&
|
||||
(
|
||||
!rule.meta || (rule.meta && (typeof rule.meta.schema === "undefined" || rule.meta.schema === null))
|
||||
)
|
||||
) {
|
||||
emitMissingSchemaWarning(ruleName);
|
||||
}
|
||||
config.rules[ruleName] = [1].concat(item.options);
|
||||
} else {
|
||||
config.rules[ruleName] = 1;
|
||||
|
|
@ -561,14 +632,18 @@ class RuleTester {
|
|||
* The goal is to check whether or not AST was modified when
|
||||
* running the rule under test.
|
||||
*/
|
||||
linter.defineRule("rule-tester/validate-ast", () => ({
|
||||
Program(node) {
|
||||
beforeAST = cloneDeeplyExcludesParent(node);
|
||||
},
|
||||
"Program:exit"(node) {
|
||||
afterAST = node;
|
||||
linter.defineRule("rule-tester/validate-ast", {
|
||||
create() {
|
||||
return {
|
||||
Program(node) {
|
||||
beforeAST = cloneDeeplyExcludesParent(node);
|
||||
},
|
||||
"Program:exit"(node) {
|
||||
afterAST = node;
|
||||
}
|
||||
};
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
if (typeof config.parser === "string") {
|
||||
assert(path.isAbsolute(config.parser), "Parsers provided as strings to RuleTester must be absolute paths");
|
||||
|
|
@ -607,7 +682,16 @@ class RuleTester {
|
|||
validate(config, "rule-tester", id => (id === ruleName ? rule : null));
|
||||
|
||||
// Verify the code.
|
||||
const messages = linter.verify(code, config, filename);
|
||||
const { getComments } = SourceCode.prototype;
|
||||
let messages;
|
||||
|
||||
try {
|
||||
SourceCode.prototype.getComments = getCommentsDeprecation;
|
||||
messages = linter.verify(code, config, filename);
|
||||
} finally {
|
||||
SourceCode.prototype.getComments = getComments;
|
||||
}
|
||||
|
||||
const fatalErrorMessage = messages.find(m => m.fatal);
|
||||
|
||||
assert(!fatalErrorMessage, `A fatal parsing error occurred: ${fatalErrorMessage && fatalErrorMessage.message}`);
|
||||
|
|
@ -656,6 +740,13 @@ class RuleTester {
|
|||
* @private
|
||||
*/
|
||||
function testValidTemplate(item) {
|
||||
const code = typeof item === "object" ? item.code : item;
|
||||
|
||||
assert.ok(typeof code === "string", "Test case must specify a string value for 'code'");
|
||||
if (item.name) {
|
||||
assert.ok(typeof item.name === "string", "Optional test case property 'name' must be a string");
|
||||
}
|
||||
|
||||
const result = runRuleForItem(item);
|
||||
const messages = result.messages;
|
||||
|
||||
|
|
@ -696,6 +787,10 @@ class RuleTester {
|
|||
* @private
|
||||
*/
|
||||
function testInvalidTemplate(item) {
|
||||
assert.ok(typeof item.code === "string", "Test case must specify a string value for 'code'");
|
||||
if (item.name) {
|
||||
assert.ok(typeof item.name === "string", "Optional test case property 'name' must be a string");
|
||||
}
|
||||
assert.ok(item.errors || item.errors === 0,
|
||||
`Did not specify errors for an invalid test of ${ruleName}`);
|
||||
|
||||
|
|
@ -921,16 +1016,6 @@ class RuleTester {
|
|||
);
|
||||
}
|
||||
|
||||
// Rules that produce fixes must have `meta.fixable` property.
|
||||
if (result.output !== item.code) {
|
||||
assert.ok(
|
||||
hasOwnProperty(rule, "meta"),
|
||||
"Fixable rules should export a `meta.fixable` property."
|
||||
);
|
||||
|
||||
// Linter throws if a rule that produced a fix has `meta` but doesn't have `meta.fixable`.
|
||||
}
|
||||
|
||||
assertASTDidntChange(result.beforeAST, result.afterAST);
|
||||
}
|
||||
|
||||
|
|
@ -938,11 +1023,11 @@ class RuleTester {
|
|||
* This creates a mocha test suite and pipes all supplied info through
|
||||
* one of the templates above.
|
||||
*/
|
||||
RuleTester.describe(ruleName, () => {
|
||||
RuleTester.describe("valid", () => {
|
||||
this.constructor.describe(ruleName, () => {
|
||||
this.constructor.describe("valid", () => {
|
||||
test.valid.forEach(valid => {
|
||||
RuleTester[valid.only ? "itOnly" : "it"](
|
||||
sanitize(typeof valid === "object" ? valid.code : valid),
|
||||
this.constructor[valid.only ? "itOnly" : "it"](
|
||||
sanitize(typeof valid === "object" ? valid.name || valid.code : valid),
|
||||
() => {
|
||||
testValidTemplate(valid);
|
||||
}
|
||||
|
|
@ -950,10 +1035,10 @@ class RuleTester {
|
|||
});
|
||||
});
|
||||
|
||||
RuleTester.describe("invalid", () => {
|
||||
this.constructor.describe("invalid", () => {
|
||||
test.invalid.forEach(invalid => {
|
||||
RuleTester[invalid.only ? "itOnly" : "it"](
|
||||
sanitize(invalid.code),
|
||||
this.constructor[invalid.only ? "itOnly" : "it"](
|
||||
sanitize(invalid.name || invalid.code),
|
||||
() => {
|
||||
testInvalidTemplate(invalid);
|
||||
}
|
||||
|
|
|
|||
12
node_modules/eslint/lib/rules/accessor-pairs.js
generated
vendored
12
node_modules/eslint/lib/rules/accessor-pairs.js
generated
vendored
|
|
@ -134,13 +134,13 @@ function isPropertyDescriptor(node) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce getter and setter pairs in objects and classes",
|
||||
category: "Best Practices",
|
||||
description: "Enforce getter and setter pairs in objects and classes",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/accessor-pairs"
|
||||
},
|
||||
|
|
@ -299,12 +299,12 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function checkPropertyDescriptor(node) {
|
||||
const namesToCheck = node.properties
|
||||
const namesToCheck = new Set(node.properties
|
||||
.filter(p => p.type === "Property" && p.kind === "init" && !p.computed)
|
||||
.map(({ key }) => key.name);
|
||||
.map(({ key }) => key.name));
|
||||
|
||||
const hasGetter = namesToCheck.includes("get");
|
||||
const hasSetter = namesToCheck.includes("set");
|
||||
const hasGetter = namesToCheck.has("get");
|
||||
const hasSetter = namesToCheck.has("set");
|
||||
|
||||
if (checkSetWithoutGet && hasSetter && !hasGetter) {
|
||||
report(node, "missingGetter");
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/array-bracket-newline.js
generated
vendored
4
node_modules/eslint/lib/rules/array-bracket-newline.js
generated
vendored
|
|
@ -11,13 +11,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce linebreaks after opening and before closing array brackets",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce linebreaks after opening and before closing array brackets",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/array-bracket-newline"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/array-bracket-spacing.js
generated
vendored
4
node_modules/eslint/lib/rules/array-bracket-spacing.js
generated
vendored
|
|
@ -10,13 +10,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent spacing inside array brackets",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce consistent spacing inside array brackets",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/array-bracket-spacing"
|
||||
},
|
||||
|
|
|
|||
8
node_modules/eslint/lib/rules/array-callback-return.js
generated
vendored
8
node_modules/eslint/lib/rules/array-callback-return.js
generated
vendored
|
|
@ -16,7 +16,7 @@ const astUtils = require("./utils/ast-utils");
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u;
|
||||
const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|flatMap|forEach|map|reduce(?:Right)?|some|sort)$/u;
|
||||
const TARGET_METHODS = /^(?:every|filter|find(?:Last)?(?:Index)?|flatMap|forEach|map|reduce(?:Right)?|some|sort)$/u;
|
||||
|
||||
/**
|
||||
* Checks a given code path segment is reachable.
|
||||
|
|
@ -125,7 +125,7 @@ function getArrayMethodName(node) {
|
|||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next: unreachable */
|
||||
/* c8 ignore next */
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -133,13 +133,13 @@ function getArrayMethodName(node) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "enforce `return` statements in callbacks of array methods",
|
||||
category: "Best Practices",
|
||||
description: "Enforce `return` statements in callbacks of array methods",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/array-callback-return"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/array-element-newline.js
generated
vendored
4
node_modules/eslint/lib/rules/array-element-newline.js
generated
vendored
|
|
@ -11,13 +11,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce line breaks after each array element",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce line breaks after each array element",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/array-element-newline"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/arrow-body-style.js
generated
vendored
4
node_modules/eslint/lib/rules/arrow-body-style.js
generated
vendored
|
|
@ -14,13 +14,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require braces around arrow function bodies",
|
||||
category: "ECMAScript 6",
|
||||
description: "Require braces around arrow function bodies",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/arrow-body-style"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/arrow-parens.js
generated
vendored
4
node_modules/eslint/lib/rules/arrow-parens.js
generated
vendored
|
|
@ -27,13 +27,13 @@ function hasBlockBody(node) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "require parentheses around arrow function arguments",
|
||||
category: "ECMAScript 6",
|
||||
description: "Require parentheses around arrow function arguments",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/arrow-parens"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/arrow-spacing.js
generated
vendored
4
node_modules/eslint/lib/rules/arrow-spacing.js
generated
vendored
|
|
@ -14,13 +14,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent spacing before and after the arrow in arrow functions",
|
||||
category: "ECMAScript 6",
|
||||
description: "Enforce consistent spacing before and after the arrow in arrow functions",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/arrow-spacing"
|
||||
},
|
||||
|
|
|
|||
6
node_modules/eslint/lib/rules/block-scoped-var.js
generated
vendored
6
node_modules/eslint/lib/rules/block-scoped-var.js
generated
vendored
|
|
@ -8,13 +8,13 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce the use of variables within the scope they are defined",
|
||||
category: "Best Practices",
|
||||
description: "Enforce the use of variables within the scope they are defined",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/block-scoped-var"
|
||||
},
|
||||
|
|
@ -113,6 +113,8 @@ module.exports = {
|
|||
"SwitchStatement:exit": exitScope,
|
||||
CatchClause: enterScope,
|
||||
"CatchClause:exit": exitScope,
|
||||
StaticBlock: enterScope,
|
||||
"StaticBlock:exit": exitScope,
|
||||
|
||||
// Finds and reports references which are outside of valid scope.
|
||||
VariableDeclaration: checkForVariables
|
||||
|
|
|
|||
17
node_modules/eslint/lib/rules/block-spacing.js
generated
vendored
17
node_modules/eslint/lib/rules/block-spacing.js
generated
vendored
|
|
@ -11,13 +11,13 @@ const util = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "disallow or enforce spaces inside of blocks after opening block and before closing block",
|
||||
category: "Stylistic Issues",
|
||||
description: "Disallow or enforce spaces inside of blocks after opening block and before closing block",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/block-spacing"
|
||||
},
|
||||
|
|
@ -41,7 +41,7 @@ module.exports = {
|
|||
|
||||
/**
|
||||
* Gets the open brace token from a given node.
|
||||
* @param {ASTNode} node A BlockStatement/SwitchStatement node to get.
|
||||
* @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to get.
|
||||
* @returns {Token} The token of the open brace.
|
||||
*/
|
||||
function getOpenBrace(node) {
|
||||
|
|
@ -51,6 +51,12 @@ module.exports = {
|
|||
}
|
||||
return sourceCode.getLastToken(node, 1);
|
||||
}
|
||||
|
||||
if (node.type === "StaticBlock") {
|
||||
return sourceCode.getFirstToken(node, { skip: 1 }); // skip the `static` token
|
||||
}
|
||||
|
||||
// "BlockStatement"
|
||||
return sourceCode.getFirstToken(node);
|
||||
}
|
||||
|
||||
|
|
@ -73,8 +79,8 @@ module.exports = {
|
|||
}
|
||||
|
||||
/**
|
||||
* Reports invalid spacing style inside braces.
|
||||
* @param {ASTNode} node A BlockStatement/SwitchStatement node to get.
|
||||
* Checks and reports invalid spacing style inside braces.
|
||||
* @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to check.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkSpacingInsideBraces(node) {
|
||||
|
|
@ -158,6 +164,7 @@ module.exports = {
|
|||
|
||||
return {
|
||||
BlockStatement: checkSpacingInsideBraces,
|
||||
StaticBlock: checkSpacingInsideBraces,
|
||||
SwitchStatement: checkSpacingInsideBraces
|
||||
};
|
||||
}
|
||||
|
|
|
|||
10
node_modules/eslint/lib/rules/brace-style.js
generated
vendored
10
node_modules/eslint/lib/rules/brace-style.js
generated
vendored
|
|
@ -11,13 +11,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent brace style for blocks",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce consistent brace style for blocks",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/brace-style"
|
||||
},
|
||||
|
|
@ -156,6 +156,12 @@ module.exports = {
|
|||
validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node));
|
||||
}
|
||||
},
|
||||
StaticBlock(node) {
|
||||
validateCurlyPair(
|
||||
sourceCode.getFirstToken(node, { skip: 1 }), // skip the `static` token
|
||||
sourceCode.getLastToken(node)
|
||||
);
|
||||
},
|
||||
ClassBody(node) {
|
||||
validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node));
|
||||
},
|
||||
|
|
|
|||
9
node_modules/eslint/lib/rules/callback-return.js
generated
vendored
9
node_modules/eslint/lib/rules/callback-return.js
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* @fileoverview Enforce return after a callback.
|
||||
* @author Jamund Ferguson
|
||||
* @deprecated in ESLint v7.0.0
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
|
|
@ -8,6 +9,7 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: true,
|
||||
|
|
@ -17,8 +19,7 @@ module.exports = {
|
|||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require `return` statements after callbacks",
|
||||
category: "Node.js and CommonJS",
|
||||
description: "Require `return` statements after callbacks",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/callback-return"
|
||||
},
|
||||
|
|
@ -52,7 +53,7 @@ module.exports = {
|
|||
if (!node.parent) {
|
||||
return null;
|
||||
}
|
||||
if (types.indexOf(node.parent.type) === -1) {
|
||||
if (!types.includes(node.parent.type)) {
|
||||
return findClosestParentOfType(node.parent, types);
|
||||
}
|
||||
return node.parent;
|
||||
|
|
@ -86,7 +87,7 @@ module.exports = {
|
|||
* @returns {boolean} Whether or not this function matches our callback name.
|
||||
*/
|
||||
function isCallback(node) {
|
||||
return containsOnlyIdentifiers(node.callee) && callbacks.indexOf(sourceCode.getText(node.callee)) > -1;
|
||||
return containsOnlyIdentifiers(node.callee) && callbacks.includes(sourceCode.getText(node.callee));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
445
node_modules/eslint/lib/rules/camelcase.js
generated
vendored
445
node_modules/eslint/lib/rules/camelcase.js
generated
vendored
|
|
@ -5,17 +5,23 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce camelcase naming convention",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce camelcase naming convention",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/camelcase"
|
||||
},
|
||||
|
|
@ -55,32 +61,25 @@ module.exports = {
|
|||
],
|
||||
|
||||
messages: {
|
||||
notCamelCase: "Identifier '{{name}}' is not in camel case."
|
||||
notCamelCase: "Identifier '{{name}}' is not in camel case.",
|
||||
notCamelCasePrivate: "#{{name}} is not in camel case."
|
||||
}
|
||||
},
|
||||
|
||||
create(context) {
|
||||
|
||||
const options = context.options[0] || {};
|
||||
let properties = options.properties || "";
|
||||
const properties = options.properties === "never" ? "never" : "always";
|
||||
const ignoreDestructuring = options.ignoreDestructuring;
|
||||
const ignoreImports = options.ignoreImports;
|
||||
const ignoreGlobals = options.ignoreGlobals;
|
||||
const allow = options.allow || [];
|
||||
|
||||
let globalScope;
|
||||
|
||||
if (properties !== "always" && properties !== "never") {
|
||||
properties = "always";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// contains reported nodes to avoid reporting twice on destructuring with shorthand notation
|
||||
const reported = [];
|
||||
const ALLOWED_PARENT_TYPES = new Set(["CallExpression", "NewExpression"]);
|
||||
const reported = new Set();
|
||||
|
||||
/**
|
||||
* Checks if a string contains an underscore and isn't all upper-case
|
||||
|
|
@ -89,9 +88,10 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function isUnderscored(name) {
|
||||
const nameBody = name.replace(/^_+|_+$/gu, "");
|
||||
|
||||
// if there's an underscore, it might be A_CONSTANT, which is okay
|
||||
return name.includes("_") && name !== name.toUpperCase();
|
||||
return nameBody.includes("_") && nameBody !== nameBody.toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -107,94 +107,76 @@ module.exports = {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if a parent of a node is an ObjectPattern.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {boolean} if the node is inside an ObjectPattern
|
||||
* Checks if a given name is good or not.
|
||||
* @param {string} name The name to check.
|
||||
* @returns {boolean} `true` if the name is good.
|
||||
* @private
|
||||
*/
|
||||
function isInsideObjectPattern(node) {
|
||||
let current = node;
|
||||
|
||||
while (current) {
|
||||
const parent = current.parent;
|
||||
|
||||
if (parent && parent.type === "Property" && parent.computed && parent.key === current) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current.type === "ObjectPattern") {
|
||||
return true;
|
||||
}
|
||||
|
||||
current = parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
function isGoodName(name) {
|
||||
return !isUnderscored(name) || isAllowed(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given node represents assignment target property in destructuring.
|
||||
*
|
||||
* For examples:
|
||||
* ({a: b.foo} = c); // => true for `foo`
|
||||
* ([a.foo] = b); // => true for `foo`
|
||||
* ([a.foo = 1] = b); // => true for `foo`
|
||||
* ({...a.foo} = b); // => true for `foo`
|
||||
* @param {ASTNode} node An Identifier node to check
|
||||
* @returns {boolean} True if the node is an assignment target property in destructuring.
|
||||
* Checks if a given identifier reference or member expression is an assignment
|
||||
* target.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {boolean} `true` if the node is an assignment target.
|
||||
*/
|
||||
function isAssignmentTargetPropertyInDestructuring(node) {
|
||||
if (
|
||||
node.parent.type === "MemberExpression" &&
|
||||
node.parent.property === node &&
|
||||
!node.parent.computed
|
||||
) {
|
||||
const effectiveParent = node.parent.parent;
|
||||
|
||||
return (
|
||||
effectiveParent.type === "Property" &&
|
||||
effectiveParent.value === node.parent &&
|
||||
effectiveParent.parent.type === "ObjectPattern" ||
|
||||
effectiveParent.type === "ArrayPattern" ||
|
||||
effectiveParent.type === "RestElement" ||
|
||||
(
|
||||
effectiveParent.type === "AssignmentPattern" &&
|
||||
effectiveParent.left === node.parent
|
||||
)
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given node represents a reference to a global variable that is not declared in the source code.
|
||||
* These identifiers will be allowed, as it is assumed that user has no control over the names of external global variables.
|
||||
* @param {ASTNode} node `Identifier` node to check.
|
||||
* @returns {boolean} `true` if the node is a reference to a global variable.
|
||||
*/
|
||||
function isReferenceToGlobalVariable(node) {
|
||||
const variable = globalScope.set.get(node.name);
|
||||
|
||||
return variable && variable.defs.length === 0 &&
|
||||
variable.references.some(ref => ref.identifier === node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given node represents a reference to a property of an object in an object literal expression.
|
||||
* This allows to differentiate between a global variable that is allowed to be used as a reference, and the key
|
||||
* of the expressed object (which shouldn't be allowed).
|
||||
* @param {ASTNode} node `Identifier` node to check.
|
||||
* @returns {boolean} `true` if the node is a property name of an object literal expression
|
||||
*/
|
||||
function isPropertyNameInObjectLiteral(node) {
|
||||
function isAssignmentTarget(node) {
|
||||
const parent = node.parent;
|
||||
|
||||
return (
|
||||
parent.type === "Property" &&
|
||||
parent.parent.type === "ObjectExpression" &&
|
||||
!parent.computed &&
|
||||
parent.key === node
|
||||
);
|
||||
switch (parent.type) {
|
||||
case "AssignmentExpression":
|
||||
case "AssignmentPattern":
|
||||
return parent.left === node;
|
||||
|
||||
case "Property":
|
||||
return (
|
||||
parent.parent.type === "ObjectPattern" &&
|
||||
parent.value === node
|
||||
);
|
||||
case "ArrayPattern":
|
||||
case "RestElement":
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given binding identifier uses the original name as-is.
|
||||
* - If it's in object destructuring or object expression, the original name is its property name.
|
||||
* - If it's in import declaration, the original name is its exported name.
|
||||
* @param {ASTNode} node The `Identifier` node to check.
|
||||
* @returns {boolean} `true` if the identifier uses the original name as-is.
|
||||
*/
|
||||
function equalsToOriginalName(node) {
|
||||
const localName = node.name;
|
||||
const valueNode = node.parent.type === "AssignmentPattern"
|
||||
? node.parent
|
||||
: node;
|
||||
const parent = valueNode.parent;
|
||||
|
||||
switch (parent.type) {
|
||||
case "Property":
|
||||
return (
|
||||
(parent.parent.type === "ObjectPattern" || parent.parent.type === "ObjectExpression") &&
|
||||
parent.value === valueNode &&
|
||||
!parent.computed &&
|
||||
parent.key.type === "Identifier" &&
|
||||
parent.key.name === localName
|
||||
);
|
||||
|
||||
case "ImportSpecifier":
|
||||
return (
|
||||
parent.local === node &&
|
||||
astUtils.getModuleExportName(parent.imported) === localName
|
||||
);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -204,122 +186,213 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function report(node) {
|
||||
if (!reported.includes(node)) {
|
||||
reported.push(node);
|
||||
context.report({ node, messageId: "notCamelCase", data: { name: node.name } });
|
||||
if (reported.has(node.range[0])) {
|
||||
return;
|
||||
}
|
||||
reported.add(node.range[0]);
|
||||
|
||||
// Report it.
|
||||
context.report({
|
||||
node,
|
||||
messageId: node.type === "PrivateIdentifier"
|
||||
? "notCamelCasePrivate"
|
||||
: "notCamelCase",
|
||||
data: { name: node.name }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports an identifier reference or a binding identifier.
|
||||
* @param {ASTNode} node The `Identifier` node to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportReferenceId(node) {
|
||||
|
||||
/*
|
||||
* For backward compatibility, if it's in callings then ignore it.
|
||||
* Not sure why it is.
|
||||
*/
|
||||
if (
|
||||
node.parent.type === "CallExpression" ||
|
||||
node.parent.type === "NewExpression"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* For backward compatibility, if it's a default value of
|
||||
* destructuring/parameters then ignore it.
|
||||
* Not sure why it is.
|
||||
*/
|
||||
if (
|
||||
node.parent.type === "AssignmentPattern" &&
|
||||
node.parent.right === node
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The `ignoreDestructuring` flag skips the identifiers that uses
|
||||
* the property name as-is.
|
||||
*/
|
||||
if (ignoreDestructuring && equalsToOriginalName(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
report(node);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
// Report camelcase of global variable references ------------------
|
||||
Program() {
|
||||
globalScope = context.getScope();
|
||||
const scope = context.getScope();
|
||||
|
||||
if (!ignoreGlobals) {
|
||||
|
||||
// Defined globals in config files or directive comments.
|
||||
for (const variable of scope.variables) {
|
||||
if (
|
||||
variable.identifiers.length > 0 ||
|
||||
isGoodName(variable.name)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
for (const reference of variable.references) {
|
||||
|
||||
/*
|
||||
* For backward compatibility, this rule reports read-only
|
||||
* references as well.
|
||||
*/
|
||||
reportReferenceId(reference.identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Undefined globals.
|
||||
for (const reference of scope.through) {
|
||||
const id = reference.identifier;
|
||||
|
||||
if (isGoodName(id.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* For backward compatibility, this rule reports read-only
|
||||
* references as well.
|
||||
*/
|
||||
reportReferenceId(id);
|
||||
}
|
||||
},
|
||||
|
||||
Identifier(node) {
|
||||
// Report camelcase of declared variables --------------------------
|
||||
[[
|
||||
"VariableDeclaration",
|
||||
"FunctionDeclaration",
|
||||
"FunctionExpression",
|
||||
"ArrowFunctionExpression",
|
||||
"ClassDeclaration",
|
||||
"ClassExpression",
|
||||
"CatchClause"
|
||||
]](node) {
|
||||
for (const variable of context.getDeclaredVariables(node)) {
|
||||
if (isGoodName(variable.name)) {
|
||||
continue;
|
||||
}
|
||||
const id = variable.identifiers[0];
|
||||
|
||||
/*
|
||||
* Leading and trailing underscores are commonly used to flag
|
||||
* private/protected identifiers, strip them before checking if underscored
|
||||
*/
|
||||
const name = node.name,
|
||||
nameIsUnderscored = isUnderscored(name.replace(/^_+|_+$/gu, "")),
|
||||
effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
|
||||
// Report declaration.
|
||||
if (!(ignoreDestructuring && equalsToOriginalName(id))) {
|
||||
report(id);
|
||||
}
|
||||
|
||||
// First, we ignore the node if it match the ignore list
|
||||
if (isAllowed(name)) {
|
||||
/*
|
||||
* For backward compatibility, report references as well.
|
||||
* It looks unnecessary because declarations are reported.
|
||||
*/
|
||||
for (const reference of variable.references) {
|
||||
if (reference.init) {
|
||||
continue; // Skip the write references of initializers.
|
||||
}
|
||||
reportReferenceId(reference.identifier);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Report camelcase in properties ----------------------------------
|
||||
[[
|
||||
"ObjectExpression > Property[computed!=true] > Identifier.key",
|
||||
"MethodDefinition[computed!=true] > Identifier.key",
|
||||
"PropertyDefinition[computed!=true] > Identifier.key",
|
||||
"MethodDefinition > PrivateIdentifier.key",
|
||||
"PropertyDefinition > PrivateIdentifier.key"
|
||||
]](node) {
|
||||
if (properties === "never" || isGoodName(node.name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's a global variable
|
||||
if (ignoreGlobals && isReferenceToGlobalVariable(node) && !isPropertyNameInObjectLiteral(node)) {
|
||||
report(node);
|
||||
},
|
||||
"MemberExpression[computed!=true] > Identifier.property"(node) {
|
||||
if (
|
||||
properties === "never" ||
|
||||
!isAssignmentTarget(node.parent) || // ← ignore read-only references.
|
||||
isGoodName(node.name)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
report(node);
|
||||
},
|
||||
|
||||
// MemberExpressions get special rules
|
||||
if (node.parent.type === "MemberExpression") {
|
||||
// Report camelcase in import --------------------------------------
|
||||
ImportDeclaration(node) {
|
||||
for (const variable of context.getDeclaredVariables(node)) {
|
||||
if (isGoodName(variable.name)) {
|
||||
continue;
|
||||
}
|
||||
const id = variable.identifiers[0];
|
||||
|
||||
// "never" check properties
|
||||
if (properties === "never") {
|
||||
return;
|
||||
// Report declaration.
|
||||
if (!(ignoreImports && equalsToOriginalName(id))) {
|
||||
report(id);
|
||||
}
|
||||
|
||||
// Always report underscored object names
|
||||
if (node.parent.object.type === "Identifier" && node.parent.object.name === node.name && nameIsUnderscored) {
|
||||
report(node);
|
||||
|
||||
// Report AssignmentExpressions only if they are the left side of the assignment
|
||||
} else if (effectiveParent.type === "AssignmentExpression" && nameIsUnderscored && (effectiveParent.right.type !== "MemberExpression" || effectiveParent.left.type === "MemberExpression" && effectiveParent.left.property.name === node.name)) {
|
||||
report(node);
|
||||
|
||||
} else if (isAssignmentTargetPropertyInDestructuring(node) && nameIsUnderscored) {
|
||||
report(node);
|
||||
/*
|
||||
* For backward compatibility, report references as well.
|
||||
* It looks unnecessary because declarations are reported.
|
||||
*/
|
||||
for (const reference of variable.references) {
|
||||
reportReferenceId(reference.identifier);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Report camelcase in re-export -----------------------------------
|
||||
[[
|
||||
"ExportAllDeclaration > Identifier.exported",
|
||||
"ExportSpecifier > Identifier.exported"
|
||||
]](node) {
|
||||
if (isGoodName(node.name)) {
|
||||
return;
|
||||
}
|
||||
report(node);
|
||||
},
|
||||
|
||||
// Report camelcase in labels --------------------------------------
|
||||
[[
|
||||
"LabeledStatement > Identifier.label",
|
||||
|
||||
/*
|
||||
* Properties have their own rules, and
|
||||
* AssignmentPattern nodes can be treated like Properties:
|
||||
* e.g.: const { no_camelcased = false } = bar;
|
||||
* For backward compatibility, report references as well.
|
||||
* It looks unnecessary because declarations are reported.
|
||||
*/
|
||||
} else if (node.parent.type === "Property" || node.parent.type === "AssignmentPattern") {
|
||||
|
||||
if (node.parent.parent && node.parent.parent.type === "ObjectPattern") {
|
||||
if (node.parent.shorthand && node.parent.value.left && nameIsUnderscored) {
|
||||
report(node);
|
||||
}
|
||||
|
||||
const assignmentKeyEqualsValue = node.parent.key.name === node.parent.value.name;
|
||||
|
||||
if (nameIsUnderscored && node.parent.computed) {
|
||||
report(node);
|
||||
}
|
||||
|
||||
// prevent checking righthand side of destructured object
|
||||
if (node.parent.key === node && node.parent.value !== node) {
|
||||
return;
|
||||
}
|
||||
|
||||
const valueIsUnderscored = node.parent.value.name && nameIsUnderscored;
|
||||
|
||||
// ignore destructuring if the option is set, unless a new identifier is created
|
||||
if (valueIsUnderscored && !(assignmentKeyEqualsValue && ignoreDestructuring)) {
|
||||
report(node);
|
||||
}
|
||||
}
|
||||
|
||||
// "never" check properties or always ignore destructuring
|
||||
if (properties === "never" || (ignoreDestructuring && isInsideObjectPattern(node))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't check right hand side of AssignmentExpression to prevent duplicate warnings
|
||||
if (nameIsUnderscored && !ALLOWED_PARENT_TYPES.has(effectiveParent.type) && !(node.parent.right === node)) {
|
||||
report(node);
|
||||
}
|
||||
|
||||
// Check if it's an import specifier
|
||||
} else if (["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"].includes(node.parent.type)) {
|
||||
|
||||
if (node.parent.type === "ImportSpecifier" && ignoreImports) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Report only if the local imported identifier is underscored
|
||||
if (
|
||||
node.parent.local &&
|
||||
node.parent.local.name === node.name &&
|
||||
nameIsUnderscored
|
||||
) {
|
||||
report(node);
|
||||
}
|
||||
|
||||
// Report anything that is underscored that isn't a CallExpression
|
||||
} else if (nameIsUnderscored && !ALLOWED_PARENT_TYPES.has(effectiveParent.type)) {
|
||||
report(node);
|
||||
"BreakStatement > Identifier.label",
|
||||
"ContinueStatement > Identifier.label"
|
||||
]](node) {
|
||||
if (isGoodName(node.name)) {
|
||||
return;
|
||||
}
|
||||
report(node);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
|||
6
node_modules/eslint/lib/rules/capitalized-comments.js
generated
vendored
6
node_modules/eslint/lib/rules/capitalized-comments.js
generated
vendored
|
|
@ -99,13 +99,13 @@ function createRegExpForIgnorePatterns(normalizedOptions) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce or disallow capitalization of the first letter of a comment",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce or disallow capitalization of the first letter of a comment",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/capitalized-comments"
|
||||
},
|
||||
|
|
@ -185,7 +185,7 @@ module.exports = {
|
|||
|
||||
return Boolean(
|
||||
previousTokenOrComment &&
|
||||
["Block", "Line"].indexOf(previousTokenOrComment.type) !== -1
|
||||
["Block", "Line"].includes(previousTokenOrComment.type)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
78
node_modules/eslint/lib/rules/class-methods-use-this.js
generated
vendored
78
node_modules/eslint/lib/rules/class-methods-use-this.js
generated
vendored
|
|
@ -15,13 +15,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce that class methods utilize `this`",
|
||||
category: "Best Practices",
|
||||
description: "Enforce that class methods utilize `this`",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/class-methods-use-this"
|
||||
},
|
||||
|
|
@ -34,6 +34,10 @@ module.exports = {
|
|||
items: {
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
enforceForClassFields: {
|
||||
type: "boolean",
|
||||
default: true
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
|
|
@ -45,10 +49,27 @@ module.exports = {
|
|||
},
|
||||
create(context) {
|
||||
const config = Object.assign({}, context.options[0]);
|
||||
const enforceForClassFields = config.enforceForClassFields !== false;
|
||||
const exceptMethods = new Set(config.exceptMethods || []);
|
||||
|
||||
const stack = [];
|
||||
|
||||
/**
|
||||
* Push `this` used flag initialized with `false` onto the stack.
|
||||
* @returns {void}
|
||||
*/
|
||||
function pushContext() {
|
||||
stack.push(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop `this` used flag from the stack.
|
||||
* @returns {boolean | undefined} `this` used flag
|
||||
*/
|
||||
function popContext() {
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the current context to false and pushes it onto the stack.
|
||||
* These booleans represent whether 'this' has been used in the context.
|
||||
|
|
@ -56,7 +77,7 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function enterFunction() {
|
||||
stack.push(false);
|
||||
pushContext();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,7 +87,14 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function isInstanceMethod(node) {
|
||||
return !node.static && node.kind !== "constructor" && node.type === "MethodDefinition";
|
||||
switch (node.type) {
|
||||
case "MethodDefinition":
|
||||
return !node.static && node.kind !== "constructor";
|
||||
case "PropertyDefinition":
|
||||
return !node.static && enforceForClassFields;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,8 +104,19 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function isIncludedInstanceMethod(node) {
|
||||
return isInstanceMethod(node) &&
|
||||
(node.computed || !exceptMethods.has(node.key.name));
|
||||
if (isInstanceMethod(node)) {
|
||||
if (node.computed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const hashIfNeeded = node.key.type === "PrivateIdentifier" ? "#" : "";
|
||||
const name = node.key.type === "Literal"
|
||||
? astUtils.getStaticStringValue(node.key)
|
||||
: (node.key.name || "");
|
||||
|
||||
return !exceptMethods.has(hashIfNeeded + name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -89,11 +128,12 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function exitFunction(node) {
|
||||
const methodUsesThis = stack.pop();
|
||||
const methodUsesThis = popContext();
|
||||
|
||||
if (isIncludedInstanceMethod(node.parent) && !methodUsesThis) {
|
||||
context.report({
|
||||
node,
|
||||
loc: astUtils.getFunctionHeadLoc(node, context.getSourceCode()),
|
||||
messageId: "missingThis",
|
||||
data: {
|
||||
name: astUtils.getFunctionNameWithKind(node)
|
||||
|
|
@ -118,8 +158,30 @@ module.exports = {
|
|||
"FunctionDeclaration:exit": exitFunction,
|
||||
FunctionExpression: enterFunction,
|
||||
"FunctionExpression:exit": exitFunction,
|
||||
|
||||
/*
|
||||
* Class field value are implicit functions.
|
||||
*/
|
||||
"PropertyDefinition > *.key:exit": pushContext,
|
||||
"PropertyDefinition:exit": popContext,
|
||||
|
||||
/*
|
||||
* Class static blocks are implicit functions. They aren't required to use `this`,
|
||||
* but we have to push context so that it captures any use of `this` in the static block
|
||||
* separately from enclosing contexts, because static blocks have their own `this` and it
|
||||
* shouldn't count as used `this` in enclosing contexts.
|
||||
*/
|
||||
StaticBlock: pushContext,
|
||||
"StaticBlock:exit": popContext,
|
||||
|
||||
ThisExpression: markThisUsed,
|
||||
Super: markThisUsed
|
||||
Super: markThisUsed,
|
||||
...(
|
||||
enforceForClassFields && {
|
||||
"PropertyDefinition > ArrowFunctionExpression.value": enterFunction,
|
||||
"PropertyDefinition > ArrowFunctionExpression.value:exit": exitFunction
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
41
node_modules/eslint/lib/rules/comma-dangle.js
generated
vendored
41
node_modules/eslint/lib/rules/comma-dangle.js
generated
vendored
|
|
@ -50,7 +50,7 @@ function normalizeOptions(optionValue, ecmaVersion) {
|
|||
objects: optionValue,
|
||||
imports: optionValue,
|
||||
exports: optionValue,
|
||||
functions: (!ecmaVersion || ecmaVersion < 8) ? "ignore" : optionValue
|
||||
functions: ecmaVersion < 2017 ? "ignore" : optionValue
|
||||
};
|
||||
}
|
||||
if (typeof optionValue === "object" && optionValue !== null) {
|
||||
|
|
@ -70,13 +70,13 @@ function normalizeOptions(optionValue, ecmaVersion) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "require or disallow trailing commas",
|
||||
category: "Stylistic Issues",
|
||||
description: "Require or disallow trailing commas",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/comma-dangle"
|
||||
},
|
||||
|
|
@ -123,7 +123,8 @@ module.exports = {
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
additionalItems: false
|
||||
},
|
||||
|
||||
messages: {
|
||||
|
|
@ -133,7 +134,7 @@ module.exports = {
|
|||
},
|
||||
|
||||
create(context) {
|
||||
const options = normalizeOptions(context.options[0], context.parserOptions.ecmaVersion);
|
||||
const options = normalizeOptions(context.options[0], context.languageOptions.ecmaVersion);
|
||||
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
|
|
@ -242,8 +243,18 @@ module.exports = {
|
|||
node: lastItem,
|
||||
loc: trailingToken.loc,
|
||||
messageId: "unexpected",
|
||||
fix(fixer) {
|
||||
return fixer.remove(trailingToken);
|
||||
*fix(fixer) {
|
||||
yield fixer.remove(trailingToken);
|
||||
|
||||
/*
|
||||
* Extend the range of the fix to include surrounding tokens to ensure
|
||||
* that the element after which the comma is removed stays _last_.
|
||||
* This intentionally makes conflicts in fix ranges with rules that may be
|
||||
* adding or removing elements in the same autofix pass.
|
||||
* https://github.com/eslint/eslint/issues/15660
|
||||
*/
|
||||
yield fixer.insertTextBefore(sourceCode.getTokenBefore(trailingToken), "");
|
||||
yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), "");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -281,8 +292,18 @@ module.exports = {
|
|||
end: astUtils.getNextLocation(sourceCode, trailingToken.loc.end)
|
||||
},
|
||||
messageId: "missing",
|
||||
fix(fixer) {
|
||||
return fixer.insertTextAfter(trailingToken, ",");
|
||||
*fix(fixer) {
|
||||
yield fixer.insertTextAfter(trailingToken, ",");
|
||||
|
||||
/*
|
||||
* Extend the range of the fix to include surrounding tokens to ensure
|
||||
* that the element after which the comma is inserted stays _last_.
|
||||
* This intentionally makes conflicts in fix ranges with rules that may be
|
||||
* adding or removing elements in the same autofix pass.
|
||||
* https://github.com/eslint/eslint/issues/15660
|
||||
*/
|
||||
yield fixer.insertTextBefore(trailingToken, "");
|
||||
yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), "");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -325,7 +346,7 @@ module.exports = {
|
|||
"always-multiline": forceTrailingCommaIfMultiline,
|
||||
"only-multiline": allowTrailingCommaIfMultiline,
|
||||
never: forbidTrailingComma,
|
||||
ignore: () => {}
|
||||
ignore() {}
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
|||
80
node_modules/eslint/lib/rules/comma-spacing.js
generated
vendored
80
node_modules/eslint/lib/rules/comma-spacing.js
generated
vendored
|
|
@ -10,13 +10,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent spacing before and after commas",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce consistent spacing before and after commas",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/comma-spacing"
|
||||
},
|
||||
|
|
@ -103,38 +103,6 @@ module.exports = {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the spacing around a comma token.
|
||||
* @param {Object} tokens The tokens to be validated.
|
||||
* @param {Token} tokens.comma The token representing the comma.
|
||||
* @param {Token} [tokens.left] The last token before the comma.
|
||||
* @param {Token} [tokens.right] The first token after the comma.
|
||||
* @param {Token|ASTNode} reportItem The item to use when reporting an error.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function validateCommaItemSpacing(tokens, reportItem) {
|
||||
if (tokens.left && astUtils.isTokenOnSameLine(tokens.left, tokens.comma) &&
|
||||
(options.before !== sourceCode.isSpaceBetweenTokens(tokens.left, tokens.comma))
|
||||
) {
|
||||
report(reportItem, "before", tokens.left);
|
||||
}
|
||||
|
||||
if (tokens.right && astUtils.isClosingParenToken(tokens.right)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tokens.right && !options.after && tokens.right.type === "Line") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tokens.right && astUtils.isTokenOnSameLine(tokens.comma, tokens.right) &&
|
||||
(options.after !== sourceCode.isSpaceBetweenTokens(tokens.comma, tokens.right))
|
||||
) {
|
||||
report(reportItem, "after", tokens.right);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds null elements of the given ArrayExpression or ArrayPattern node to the ignore list.
|
||||
* @param {ASTNode} node An ArrayExpression or ArrayPattern node.
|
||||
|
|
@ -172,18 +140,44 @@ module.exports = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (token && token.type === "JSXText") {
|
||||
return;
|
||||
}
|
||||
|
||||
const previousToken = tokensAndComments[i - 1];
|
||||
const nextToken = tokensAndComments[i + 1];
|
||||
|
||||
validateCommaItemSpacing({
|
||||
comma: token,
|
||||
left: astUtils.isCommaToken(previousToken) || commaTokensToIgnore.includes(token) ? null : previousToken,
|
||||
right: astUtils.isCommaToken(nextToken) ? null : nextToken
|
||||
}, token);
|
||||
if (
|
||||
previousToken &&
|
||||
!astUtils.isCommaToken(previousToken) && // ignore spacing between two commas
|
||||
|
||||
/*
|
||||
* `commaTokensToIgnore` are ending commas of `null` elements (array holes/elisions).
|
||||
* In addition to spacing between two commas, this can also ignore:
|
||||
*
|
||||
* - Spacing after `[` (controlled by array-bracket-spacing)
|
||||
* Example: [ , ]
|
||||
* ^
|
||||
* - Spacing after a comment (for backwards compatibility, this was possibly unintentional)
|
||||
* Example: [a, /* * / ,]
|
||||
* ^
|
||||
*/
|
||||
!commaTokensToIgnore.includes(token) &&
|
||||
|
||||
astUtils.isTokenOnSameLine(previousToken, token) &&
|
||||
options.before !== sourceCode.isSpaceBetweenTokens(previousToken, token)
|
||||
) {
|
||||
report(token, "before", previousToken);
|
||||
}
|
||||
|
||||
if (
|
||||
nextToken &&
|
||||
!astUtils.isCommaToken(nextToken) && // ignore spacing between two commas
|
||||
!astUtils.isClosingParenToken(nextToken) && // controlled by space-in-parens
|
||||
!astUtils.isClosingBracketToken(nextToken) && // controlled by array-bracket-spacing
|
||||
!astUtils.isClosingBraceToken(nextToken) && // controlled by object-curly-spacing
|
||||
!(!options.after && nextToken.type === "Line") && // special case, allow space before line comment
|
||||
astUtils.isTokenOnSameLine(token, nextToken) &&
|
||||
options.after !== sourceCode.isSpaceBetweenTokens(token, nextToken)
|
||||
) {
|
||||
report(token, "after", nextToken);
|
||||
}
|
||||
});
|
||||
},
|
||||
ArrayExpression: addNullElementsToIgnoreList,
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/comma-style.js
generated
vendored
4
node_modules/eslint/lib/rules/comma-style.js
generated
vendored
|
|
@ -11,13 +11,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent comma style",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce consistent comma style",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/comma-style"
|
||||
},
|
||||
|
|
|
|||
114
node_modules/eslint/lib/rules/complexity.js
generated
vendored
114
node_modules/eslint/lib/rules/complexity.js
generated
vendored
|
|
@ -17,13 +17,13 @@ const { upperCaseFirst } = require("../shared/string-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce a maximum cyclomatic complexity allowed in a program",
|
||||
category: "Best Practices",
|
||||
description: "Enforce a maximum cyclomatic complexity allowed in a program",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/complexity"
|
||||
},
|
||||
|
|
@ -75,60 +75,16 @@ module.exports = {
|
|||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Using a stack to store complexity (handling nested functions)
|
||||
const fns = [];
|
||||
// Using a stack to store complexity per code path
|
||||
const complexities = [];
|
||||
|
||||
/**
|
||||
* When parsing a new function, store it in our function stack
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function startFunction() {
|
||||
fns.push(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the node at the end of function
|
||||
* @param {ASTNode} node node to evaluate
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function endFunction(node) {
|
||||
const name = upperCaseFirst(astUtils.getFunctionNameWithKind(node));
|
||||
const complexity = fns.pop();
|
||||
|
||||
if (complexity > THRESHOLD) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "complex",
|
||||
data: { name, complexity, max: THRESHOLD }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the complexity of the function in context
|
||||
* Increase the complexity of the code path in context
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function increaseComplexity() {
|
||||
if (fns.length) {
|
||||
fns[fns.length - 1]++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the switch complexity in context
|
||||
* @param {ASTNode} node node to evaluate
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function increaseSwitchComplexity(node) {
|
||||
|
||||
// Avoiding `default`
|
||||
if (node.test) {
|
||||
increaseComplexity();
|
||||
}
|
||||
complexities[complexities.length - 1]++;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
@ -136,13 +92,14 @@ module.exports = {
|
|||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
FunctionDeclaration: startFunction,
|
||||
FunctionExpression: startFunction,
|
||||
ArrowFunctionExpression: startFunction,
|
||||
"FunctionDeclaration:exit": endFunction,
|
||||
"FunctionExpression:exit": endFunction,
|
||||
"ArrowFunctionExpression:exit": endFunction,
|
||||
|
||||
onCodePathStart() {
|
||||
|
||||
// The initial complexity is 1, representing one execution path in the CodePath
|
||||
complexities.push(1);
|
||||
},
|
||||
|
||||
// Each branching in the code adds 1 to the complexity
|
||||
CatchClause: increaseComplexity,
|
||||
ConditionalExpression: increaseComplexity,
|
||||
LogicalExpression: increaseComplexity,
|
||||
|
|
@ -150,14 +107,57 @@ module.exports = {
|
|||
ForInStatement: increaseComplexity,
|
||||
ForOfStatement: increaseComplexity,
|
||||
IfStatement: increaseComplexity,
|
||||
SwitchCase: increaseSwitchComplexity,
|
||||
WhileStatement: increaseComplexity,
|
||||
DoWhileStatement: increaseComplexity,
|
||||
|
||||
// Avoid `default`
|
||||
"SwitchCase[test]": increaseComplexity,
|
||||
|
||||
// Logical assignment operators have short-circuiting behavior
|
||||
AssignmentExpression(node) {
|
||||
if (astUtils.isLogicalAssignmentOperator(node.operator)) {
|
||||
increaseComplexity();
|
||||
}
|
||||
},
|
||||
|
||||
onCodePathEnd(codePath, node) {
|
||||
const complexity = complexities.pop();
|
||||
|
||||
/*
|
||||
* This rule only evaluates complexity of functions, so "program" is excluded.
|
||||
* Class field initializers and class static blocks are implicit functions. Therefore,
|
||||
* they shouldn't contribute to the enclosing function's complexity, but their
|
||||
* own complexity should be evaluated.
|
||||
*/
|
||||
if (
|
||||
codePath.origin !== "function" &&
|
||||
codePath.origin !== "class-field-initializer" &&
|
||||
codePath.origin !== "class-static-block"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (complexity > THRESHOLD) {
|
||||
let name;
|
||||
|
||||
if (codePath.origin === "class-field-initializer") {
|
||||
name = "class field initializer";
|
||||
} else if (codePath.origin === "class-static-block") {
|
||||
name = "class static block";
|
||||
} else {
|
||||
name = astUtils.getFunctionNameWithKind(node);
|
||||
}
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: "complex",
|
||||
data: {
|
||||
name: upperCaseFirst(name),
|
||||
complexity,
|
||||
max: THRESHOLD
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
7
node_modules/eslint/lib/rules/computed-property-spacing.js
generated
vendored
7
node_modules/eslint/lib/rules/computed-property-spacing.js
generated
vendored
|
|
@ -10,13 +10,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent spacing inside computed property brackets",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce consistent spacing inside computed property brackets",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/computed-property-spacing"
|
||||
},
|
||||
|
|
@ -195,7 +195,8 @@ module.exports = {
|
|||
};
|
||||
|
||||
if (enforceForClassMembers) {
|
||||
listeners.MethodDefinition = checkSpacing("key");
|
||||
listeners.MethodDefinition =
|
||||
listeners.PropertyDefinition = listeners.Property;
|
||||
}
|
||||
|
||||
return listeners;
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/consistent-return.js
generated
vendored
4
node_modules/eslint/lib/rules/consistent-return.js
generated
vendored
|
|
@ -40,13 +40,13 @@ function isClassConstructor(node) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require `return` statements to either always or never specify values",
|
||||
category: "Best Practices",
|
||||
description: "Require `return` statements to either always or never specify values",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/consistent-return"
|
||||
},
|
||||
|
|
|
|||
8
node_modules/eslint/lib/rules/consistent-this.js
generated
vendored
8
node_modules/eslint/lib/rules/consistent-this.js
generated
vendored
|
|
@ -8,13 +8,13 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent naming when capturing the current execution context",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce consistent naming when capturing the current execution context",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/consistent-this"
|
||||
},
|
||||
|
|
@ -47,7 +47,7 @@ module.exports = {
|
|||
* Reports that a variable declarator or assignment expression is assigning
|
||||
* a non-'this' value to the specified alias.
|
||||
* @param {ASTNode} node The assigning node.
|
||||
* @param {string} name the name of the alias that was incorrectly used.
|
||||
* @param {string} name the name of the alias that was incorrectly used.
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportBadAssignment(node, name) {
|
||||
|
|
@ -65,7 +65,7 @@ module.exports = {
|
|||
function checkAssignment(node, name, value) {
|
||||
const isThis = value.type === "ThisExpression";
|
||||
|
||||
if (aliases.indexOf(name) !== -1) {
|
||||
if (aliases.includes(name)) {
|
||||
if (!isThis || node.operator && node.operator !== "=") {
|
||||
reportBadAssignment(node, name);
|
||||
}
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/constructor-super.js
generated
vendored
4
node_modules/eslint/lib/rules/constructor-super.js
generated
vendored
|
|
@ -116,13 +116,13 @@ function isPossibleConstructor(node) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "require `super()` calls in constructors",
|
||||
category: "ECMAScript 6",
|
||||
description: "Require `super()` calls in constructors",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/rules/constructor-super"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/curly.js
generated
vendored
4
node_modules/eslint/lib/rules/curly.js
generated
vendored
|
|
@ -14,13 +14,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent brace style for all control statements",
|
||||
category: "Best Practices",
|
||||
description: "Enforce consistent brace style for all control statements",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/curly"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/default-case-last.js
generated
vendored
4
node_modules/eslint/lib/rules/default-case-last.js
generated
vendored
|
|
@ -9,13 +9,13 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce default clauses in switch statements to be last",
|
||||
category: "Best Practices",
|
||||
description: "Enforce default clauses in switch statements to be last",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/default-case-last"
|
||||
},
|
||||
|
|
|
|||
8
node_modules/eslint/lib/rules/default-case.js
generated
vendored
8
node_modules/eslint/lib/rules/default-case.js
generated
vendored
|
|
@ -10,13 +10,13 @@ const DEFAULT_COMMENT_PATTERN = /^no default$/iu;
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require `default` cases in `switch` statements",
|
||||
category: "Best Practices",
|
||||
description: "Require `default` cases in `switch` statements",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/default-case"
|
||||
},
|
||||
|
|
@ -50,8 +50,8 @@ module.exports = {
|
|||
|
||||
/**
|
||||
* Shortcut to get last element of array
|
||||
* @param {*[]} collection Array
|
||||
* @returns {*} Last element
|
||||
* @param {*[]} collection Array
|
||||
* @returns {any} Last element
|
||||
*/
|
||||
function last(collection) {
|
||||
return collection[collection.length - 1];
|
||||
|
|
|
|||
6
node_modules/eslint/lib/rules/default-param-last.js
generated
vendored
6
node_modules/eslint/lib/rules/default-param-last.js
generated
vendored
|
|
@ -5,13 +5,13 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce default parameters to be last",
|
||||
category: "Best Practices",
|
||||
description: "Enforce default parameters to be last",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/default-param-last"
|
||||
},
|
||||
|
|
@ -25,8 +25,8 @@ module.exports = {
|
|||
|
||||
create(context) {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* Handler for function contexts.
|
||||
* @param {ASTNode} node function node
|
||||
* @returns {void}
|
||||
*/
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/dot-location.js
generated
vendored
4
node_modules/eslint/lib/rules/dot-location.js
generated
vendored
|
|
@ -11,13 +11,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent newlines before and after dots",
|
||||
category: "Best Practices",
|
||||
description: "Enforce consistent newlines before and after dots",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/dot-location"
|
||||
},
|
||||
|
|
|
|||
9
node_modules/eslint/lib/rules/dot-notation.js
generated
vendored
9
node_modules/eslint/lib/rules/dot-notation.js
generated
vendored
|
|
@ -20,13 +20,13 @@ const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/u;
|
|||
// `null` literal must be handled separately.
|
||||
const literalTypesToCheck = new Set(["string", "boolean"]);
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce dot notation whenever possible",
|
||||
category: "Best Practices",
|
||||
description: "Enforce dot notation whenever possible",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/dot-notation"
|
||||
},
|
||||
|
|
@ -76,7 +76,7 @@ module.exports = {
|
|||
function checkComputedProperty(node, value) {
|
||||
if (
|
||||
validIdentifier.test(value) &&
|
||||
(allowKeywords || keywords.indexOf(String(value)) === -1) &&
|
||||
(allowKeywords || !keywords.includes(String(value))) &&
|
||||
!(allowPattern && allowPattern.test(value))
|
||||
) {
|
||||
const formattedValue = node.property.type === "Literal" ? JSON.stringify(value) : `\`${value}\``;
|
||||
|
|
@ -141,7 +141,8 @@ module.exports = {
|
|||
if (
|
||||
!allowKeywords &&
|
||||
!node.computed &&
|
||||
keywords.indexOf(String(node.property.name)) !== -1
|
||||
node.property.type === "Identifier" &&
|
||||
keywords.includes(String(node.property.name))
|
||||
) {
|
||||
context.report({
|
||||
node: node.property,
|
||||
|
|
|
|||
11
node_modules/eslint/lib/rules/eol-last.js
generated
vendored
11
node_modules/eslint/lib/rules/eol-last.js
generated
vendored
|
|
@ -8,13 +8,13 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "require or disallow newline at the end of files",
|
||||
category: "Stylistic Issues",
|
||||
description: "Require or disallow newline at the end of files",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/eol-last"
|
||||
},
|
||||
|
|
@ -86,10 +86,15 @@ module.exports = {
|
|||
});
|
||||
} else if (mode === "never" && endsWithNewline) {
|
||||
|
||||
const secondLastLine = sourceCode.lines[sourceCode.lines.length - 2];
|
||||
|
||||
// File is newline-terminated, but shouldn't be
|
||||
context.report({
|
||||
node,
|
||||
loc: location,
|
||||
loc: {
|
||||
start: { line: sourceCode.lines.length - 1, column: secondLastLine.length },
|
||||
end: { line: sourceCode.lines.length, column: 0 }
|
||||
},
|
||||
messageId: "unexpected",
|
||||
fix(fixer) {
|
||||
const finalEOLs = /(?:\r?\n)+$/u,
|
||||
|
|
|
|||
6
node_modules/eslint/lib/rules/eqeqeq.js
generated
vendored
6
node_modules/eslint/lib/rules/eqeqeq.js
generated
vendored
|
|
@ -15,13 +15,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require the use of `===` and `!==`",
|
||||
category: "Best Practices",
|
||||
description: "Require the use of `===` and `!==`",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/eqeqeq"
|
||||
},
|
||||
|
|
@ -78,7 +78,7 @@ module.exports = {
|
|||
|
||||
/**
|
||||
* Checks if an expression is a typeof expression
|
||||
* @param {ASTNode} node The node to check
|
||||
* @param {ASTNode} node The node to check
|
||||
* @returns {boolean} if the node is a typeof expression
|
||||
*/
|
||||
function isTypeOf(node) {
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/for-direction.js
generated
vendored
4
node_modules/eslint/lib/rules/for-direction.js
generated
vendored
|
|
@ -9,13 +9,13 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "enforce \"for\" loop update clause moving the counter in the right direction.",
|
||||
category: "Possible Errors",
|
||||
description: "Enforce \"for\" loop update clause moving the counter in the right direction",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/rules/for-direction"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/func-call-spacing.js
generated
vendored
4
node_modules/eslint/lib/rules/func-call-spacing.js
generated
vendored
|
|
@ -15,13 +15,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "require or disallow spacing between function identifiers and their invocations",
|
||||
category: "Stylistic Issues",
|
||||
description: "Require or disallow spacing between function identifiers and their invocations",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/func-call-spacing"
|
||||
},
|
||||
|
|
|
|||
22
node_modules/eslint/lib/rules/func-name-matching.js
generated
vendored
22
node_modules/eslint/lib/rules/func-name-matching.js
generated
vendored
|
|
@ -44,7 +44,7 @@ function isModuleExports(pattern) {
|
|||
* @returns {boolean} True if the string is a valid identifier
|
||||
*/
|
||||
function isIdentifier(name, ecmaVersion) {
|
||||
if (ecmaVersion >= 6) {
|
||||
if (ecmaVersion >= 2015) {
|
||||
return esutils.keyword.isIdentifierES6(name);
|
||||
}
|
||||
return esutils.keyword.isIdentifierES5(name);
|
||||
|
|
@ -68,13 +68,13 @@ const optionsObject = {
|
|||
additionalProperties: false
|
||||
};
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require function names to match the name of the variable or property to which they are assigned",
|
||||
category: "Stylistic Issues",
|
||||
description: "Require function names to match the name of the variable or property to which they are assigned",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/func-name-matching"
|
||||
},
|
||||
|
|
@ -104,7 +104,7 @@ module.exports = {
|
|||
const nameMatches = typeof context.options[0] === "string" ? context.options[0] : "always";
|
||||
const considerPropertyDescriptor = options.considerPropertyDescriptor;
|
||||
const includeModuleExports = options.includeCommonJSModuleExports;
|
||||
const ecmaVersion = context.parserOptions && context.parserOptions.ecmaVersion ? context.parserOptions.ecmaVersion : 5;
|
||||
const ecmaVersion = context.languageOptions.ecmaVersion;
|
||||
|
||||
/**
|
||||
* Check whether node is a certain CallExpression.
|
||||
|
|
@ -196,21 +196,25 @@ module.exports = {
|
|||
const isProp = node.left.type === "MemberExpression";
|
||||
const name = isProp ? astUtils.getStaticPropertyName(node.left) : node.left.name;
|
||||
|
||||
if (node.right.id && isIdentifier(name) && shouldWarn(name, node.right.id.name)) {
|
||||
if (node.right.id && name && isIdentifier(name) && shouldWarn(name, node.right.id.name)) {
|
||||
report(node, name, node.right.id.name, isProp);
|
||||
}
|
||||
},
|
||||
|
||||
Property(node) {
|
||||
if (node.value.type !== "FunctionExpression" || !node.value.id || node.computed && !isStringLiteral(node.key)) {
|
||||
"Property, PropertyDefinition[value]"(node) {
|
||||
if (!(node.value.type === "FunctionExpression" && node.value.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.key.type === "Identifier") {
|
||||
if (node.key.type === "Identifier" && !node.computed) {
|
||||
const functionName = node.value.id.name;
|
||||
let propertyName = node.key.name;
|
||||
|
||||
if (considerPropertyDescriptor && propertyName === "value") {
|
||||
if (
|
||||
considerPropertyDescriptor &&
|
||||
propertyName === "value" &&
|
||||
node.parent.type === "ObjectExpression"
|
||||
) {
|
||||
if (isPropertyCall("Object", "defineProperty", node.parent.parent) || isPropertyCall("Reflect", "defineProperty", node.parent.parent)) {
|
||||
const property = node.parent.parent.arguments[1];
|
||||
|
||||
|
|
|
|||
5
node_modules/eslint/lib/rules/func-names.js
generated
vendored
5
node_modules/eslint/lib/rules/func-names.js
generated
vendored
|
|
@ -24,13 +24,13 @@ function isFunctionName(variable) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require or disallow named `function` expressions",
|
||||
category: "Stylistic Issues",
|
||||
description: "Require or disallow named `function` expressions",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/func-names"
|
||||
},
|
||||
|
|
@ -118,6 +118,7 @@ module.exports = {
|
|||
return isObjectOrClassMethod(node) ||
|
||||
(parent.type === "VariableDeclarator" && parent.id.type === "Identifier" && parent.init === node) ||
|
||||
(parent.type === "Property" && parent.value === node) ||
|
||||
(parent.type === "PropertyDefinition" && parent.value === node) ||
|
||||
(parent.type === "AssignmentExpression" && parent.left.type === "Identifier" && parent.right === node) ||
|
||||
(parent.type === "AssignmentPattern" && parent.left.type === "Identifier" && parent.right === node);
|
||||
}
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/func-style.js
generated
vendored
4
node_modules/eslint/lib/rules/func-style.js
generated
vendored
|
|
@ -8,13 +8,13 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce the consistent use of either `function` declarations or expressions",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce the consistent use of either `function` declarations or expressions",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/func-style"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/function-call-argument-newline.js
generated
vendored
4
node_modules/eslint/lib/rules/function-call-argument-newline.js
generated
vendored
|
|
@ -9,13 +9,13 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce line breaks between arguments of a function call",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce line breaks between arguments of a function call",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/function-call-argument-newline"
|
||||
},
|
||||
|
|
|
|||
22
node_modules/eslint/lib/rules/function-paren-newline.js
generated
vendored
22
node_modules/eslint/lib/rules/function-paren-newline.js
generated
vendored
|
|
@ -14,13 +14,13 @@ const astUtils = require("./utils/ast-utils");
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent line breaks inside function parentheses",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce consistent line breaks inside function parentheses",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/function-paren-newline"
|
||||
},
|
||||
|
|
@ -183,6 +183,7 @@ module.exports = {
|
|||
/**
|
||||
* Gets the left paren and right paren tokens of a node.
|
||||
* @param {ASTNode} node The node with parens
|
||||
* @throws {TypeError} Unexpected node type.
|
||||
* @returns {Object} An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token.
|
||||
* Can also return `null` if an expression has no parens (e.g. a NewExpression with no arguments, or an ArrowFunctionExpression
|
||||
* with a single parameter)
|
||||
|
|
@ -190,10 +191,13 @@ module.exports = {
|
|||
function getParenTokens(node) {
|
||||
switch (node.type) {
|
||||
case "NewExpression":
|
||||
if (!node.arguments.length && !(
|
||||
astUtils.isOpeningParenToken(sourceCode.getLastToken(node, { skip: 1 })) &&
|
||||
astUtils.isClosingParenToken(sourceCode.getLastToken(node))
|
||||
)) {
|
||||
if (!node.arguments.length &&
|
||||
!(
|
||||
astUtils.isOpeningParenToken(sourceCode.getLastToken(node, { skip: 1 })) &&
|
||||
astUtils.isClosingParenToken(sourceCode.getLastToken(node)) &&
|
||||
node.callee.range[1] < node.range[1]
|
||||
)
|
||||
) {
|
||||
|
||||
// If the NewExpression does not have parens (e.g. `new Foo`), return null.
|
||||
return null;
|
||||
|
|
@ -226,9 +230,13 @@ module.exports = {
|
|||
return null;
|
||||
}
|
||||
|
||||
const rightParen = node.params.length
|
||||
? sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isClosingParenToken)
|
||||
: sourceCode.getTokenAfter(firstToken);
|
||||
|
||||
return {
|
||||
leftParen: firstToken,
|
||||
rightParen: sourceCode.getTokenBefore(node.body, astUtils.isClosingParenToken)
|
||||
rightParen
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/generator-star-spacing.js
generated
vendored
4
node_modules/eslint/lib/rules/generator-star-spacing.js
generated
vendored
|
|
@ -25,13 +25,13 @@ const OVERRIDE_SCHEMA = {
|
|||
]
|
||||
};
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent spacing around `*` operators in generator functions",
|
||||
category: "ECMAScript 6",
|
||||
description: "Enforce consistent spacing around `*` operators in generator functions",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/generator-star-spacing"
|
||||
},
|
||||
|
|
|
|||
26
node_modules/eslint/lib/rules/getter-return.js
generated
vendored
26
node_modules/eslint/lib/rules/getter-return.js
generated
vendored
|
|
@ -29,13 +29,13 @@ function isReachable(segment) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "enforce `return` statements in getters",
|
||||
category: "Possible Errors",
|
||||
description: "Enforce `return` statements in getters",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/rules/getter-return"
|
||||
},
|
||||
|
|
@ -112,18 +112,24 @@ module.exports = {
|
|||
}
|
||||
if (parent.type === "Property" && astUtils.getStaticPropertyName(parent) === "get" && parent.parent.type === "ObjectExpression") {
|
||||
|
||||
// Object.defineProperty()
|
||||
if (parent.parent.parent.type === "CallExpression" &&
|
||||
astUtils.getStaticPropertyName(parent.parent.parent.callee) === "defineProperty") {
|
||||
return true;
|
||||
// Object.defineProperty() or Reflect.defineProperty()
|
||||
if (parent.parent.parent.type === "CallExpression") {
|
||||
const callNode = parent.parent.parent.callee;
|
||||
|
||||
if (astUtils.isSpecificMemberAccess(callNode, "Object", "defineProperty") ||
|
||||
astUtils.isSpecificMemberAccess(callNode, "Reflect", "defineProperty")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Object.defineProperties()
|
||||
// Object.defineProperties() or Object.create()
|
||||
if (parent.parent.parent.type === "Property" &&
|
||||
parent.parent.parent.parent.type === "ObjectExpression" &&
|
||||
parent.parent.parent.parent.parent.type === "CallExpression" &&
|
||||
astUtils.getStaticPropertyName(parent.parent.parent.parent.parent.callee) === "defineProperties") {
|
||||
return true;
|
||||
parent.parent.parent.parent.parent.type === "CallExpression") {
|
||||
const callNode = parent.parent.parent.parent.parent.callee;
|
||||
|
||||
return astUtils.isSpecificMemberAccess(callNode, "Object", "defineProperties") ||
|
||||
astUtils.isSpecificMemberAccess(callNode, "Object", "create");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
node_modules/eslint/lib/rules/global-require.js
generated
vendored
14
node_modules/eslint/lib/rules/global-require.js
generated
vendored
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* @fileoverview Rule for disallowing require() outside of the top-level module context
|
||||
* @author Jamund Ferguson
|
||||
* @deprecated in ESLint v7.0.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const ACCEPTABLE_PARENTS = [
|
||||
const ACCEPTABLE_PARENTS = new Set([
|
||||
"AssignmentExpression",
|
||||
"VariableDeclarator",
|
||||
"MemberExpression",
|
||||
|
|
@ -15,7 +16,7 @@ const ACCEPTABLE_PARENTS = [
|
|||
"Program",
|
||||
"VariableDeclaration",
|
||||
"ChainExpression"
|
||||
];
|
||||
]);
|
||||
|
||||
/**
|
||||
* Finds the eslint-scope reference in the given scope.
|
||||
|
|
@ -27,10 +28,11 @@ function findReference(scope, node) {
|
|||
const references = scope.references.filter(reference => reference.identifier.range[0] === node.range[0] &&
|
||||
reference.identifier.range[1] === node.range[1]);
|
||||
|
||||
/* istanbul ignore else: correctly returns null */
|
||||
if (references.length === 1) {
|
||||
return references[0];
|
||||
}
|
||||
|
||||
/* c8 ignore next */
|
||||
return null;
|
||||
|
||||
}
|
||||
|
|
@ -47,6 +49,7 @@ function isShadowed(scope, node) {
|
|||
return reference && reference.resolved && reference.resolved.defs.length > 0;
|
||||
}
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: true,
|
||||
|
|
@ -56,8 +59,7 @@ module.exports = {
|
|||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require `require()` calls to be placed at top-level module scope",
|
||||
category: "Node.js and CommonJS",
|
||||
description: "Require `require()` calls to be placed at top-level module scope",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/global-require"
|
||||
},
|
||||
|
|
@ -74,7 +76,7 @@ module.exports = {
|
|||
const currentScope = context.getScope();
|
||||
|
||||
if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) {
|
||||
const isGoodRequire = context.getAncestors().every(parent => ACCEPTABLE_PARENTS.indexOf(parent.type) > -1);
|
||||
const isGoodRequire = context.getAncestors().every(parent => ACCEPTABLE_PARENTS.has(parent.type));
|
||||
|
||||
if (!isGoodRequire) {
|
||||
context.report({ node, messageId: "unexpected" });
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/grouped-accessor-pairs.js
generated
vendored
4
node_modules/eslint/lib/rules/grouped-accessor-pairs.js
generated
vendored
|
|
@ -90,13 +90,13 @@ function isAccessorKind(node) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require grouped accessor pairs in object literals and classes",
|
||||
category: "Best Practices",
|
||||
description: "Require grouped accessor pairs in object literals and classes",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/grouped-accessor-pairs"
|
||||
},
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/guard-for-in.js
generated
vendored
4
node_modules/eslint/lib/rules/guard-for-in.js
generated
vendored
|
|
@ -9,13 +9,13 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require `for-in` loops to include an `if` statement",
|
||||
category: "Best Practices",
|
||||
description: "Require `for-in` loops to include an `if` statement",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/guard-for-in"
|
||||
},
|
||||
|
|
|
|||
5
node_modules/eslint/lib/rules/handle-callback-err.js
generated
vendored
5
node_modules/eslint/lib/rules/handle-callback-err.js
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* @fileoverview Ensure handling of errors when we know they exist.
|
||||
* @author Jamund Ferguson
|
||||
* @deprecated in ESLint v7.0.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
|
@ -9,6 +10,7 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: true,
|
||||
|
|
@ -18,8 +20,7 @@ module.exports = {
|
|||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require error handling in callbacks",
|
||||
category: "Node.js and CommonJS",
|
||||
description: "Require error handling in callbacks",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/handle-callback-err"
|
||||
},
|
||||
|
|
|
|||
20
node_modules/eslint/lib/rules/id-blacklist.js
generated
vendored
20
node_modules/eslint/lib/rules/id-blacklist.js
generated
vendored
|
|
@ -2,6 +2,7 @@
|
|||
* @fileoverview Rule that warns when identifier names that are
|
||||
* specified in the configuration are used.
|
||||
* @author Keith Cirkel (http://keithcirkel.co.uk)
|
||||
* @deprecated in ESLint v7.5.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
|
@ -109,6 +110,7 @@ function isShorthandPropertyDefinition(node) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: true,
|
||||
|
|
@ -117,8 +119,7 @@ module.exports = {
|
|||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "disallow specified identifiers",
|
||||
category: "Stylistic Issues",
|
||||
description: "Disallow specified identifiers",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/id-blacklist"
|
||||
},
|
||||
|
|
@ -205,7 +206,17 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function report(node) {
|
||||
if (!reportedNodes.has(node)) {
|
||||
|
||||
/*
|
||||
* We used the range instead of the node because it's possible
|
||||
* for the same identifier to be represented by two different
|
||||
* nodes, with the most clear example being shorthand properties:
|
||||
* { foo }
|
||||
* In this case, "foo" is represented by one node for the name
|
||||
* and one for the value. The only way to know they are the same
|
||||
* is to look at the range.
|
||||
*/
|
||||
if (!reportedNodes.has(node.range.toString())) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "restricted",
|
||||
|
|
@ -213,8 +224,9 @@ module.exports = {
|
|||
name: node.name
|
||||
}
|
||||
});
|
||||
reportedNodes.add(node);
|
||||
reportedNodes.add(node.range.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
61
node_modules/eslint/lib/rules/id-denylist.js
generated
vendored
61
node_modules/eslint/lib/rules/id-denylist.js
generated
vendored
|
|
@ -69,14 +69,14 @@ function isRenamedImport(node) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given node is a renamed identifier node in an ObjectPattern destructuring.
|
||||
* Checks whether the given node is an ObjectPattern destructuring.
|
||||
*
|
||||
* Examples:
|
||||
* const { a : b } = foo; // node `a` is renamed node.
|
||||
* const { a : b } = foo;
|
||||
* @param {ASTNode} node `Identifier` node to check.
|
||||
* @returns {boolean} `true` if the node is a renamed node in an ObjectPattern destructuring.
|
||||
* @returns {boolean} `true` if the node is in an ObjectPattern destructuring.
|
||||
*/
|
||||
function isRenamedInDestructuring(node) {
|
||||
function isPropertyNameInDestructuring(node) {
|
||||
const parent = node.parent;
|
||||
|
||||
return (
|
||||
|
|
@ -84,38 +84,22 @@ function isRenamedInDestructuring(node) {
|
|||
!parent.computed &&
|
||||
parent.type === "Property" &&
|
||||
parent.parent.type === "ObjectPattern" &&
|
||||
parent.value !== node &&
|
||||
parent.key === node
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given node represents shorthand definition of a property in an object literal.
|
||||
* @param {ASTNode} node `Identifier` node to check.
|
||||
* @returns {boolean} `true` if the node is a shorthand property definition.
|
||||
*/
|
||||
function isShorthandPropertyDefinition(node) {
|
||||
const parent = node.parent;
|
||||
|
||||
return (
|
||||
parent.type === "Property" &&
|
||||
parent.parent.type === "ObjectExpression" &&
|
||||
parent.shorthand
|
||||
);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "disallow specified identifiers",
|
||||
category: "Stylistic Issues",
|
||||
description: "Disallow specified identifiers",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/id-denylist"
|
||||
},
|
||||
|
|
@ -128,7 +112,8 @@ module.exports = {
|
|||
uniqueItems: true
|
||||
},
|
||||
messages: {
|
||||
restricted: "Identifier '{{name}}' is restricted."
|
||||
restricted: "Identifier '{{name}}' is restricted.",
|
||||
restrictedPrivate: "Identifier '#{{name}}' is restricted."
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -187,11 +172,8 @@ module.exports = {
|
|||
parent.type !== "CallExpression" &&
|
||||
parent.type !== "NewExpression" &&
|
||||
!isRenamedImport(node) &&
|
||||
!isRenamedInDestructuring(node) &&
|
||||
!(
|
||||
isReferenceToGlobalVariable(node) &&
|
||||
!isShorthandPropertyDefinition(node)
|
||||
)
|
||||
!isPropertyNameInDestructuring(node) &&
|
||||
!isReferenceToGlobalVariable(node)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -202,15 +184,27 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function report(node) {
|
||||
if (!reportedNodes.has(node)) {
|
||||
|
||||
/*
|
||||
* We used the range instead of the node because it's possible
|
||||
* for the same identifier to be represented by two different
|
||||
* nodes, with the most clear example being shorthand properties:
|
||||
* { foo }
|
||||
* In this case, "foo" is represented by one node for the name
|
||||
* and one for the value. The only way to know they are the same
|
||||
* is to look at the range.
|
||||
*/
|
||||
if (!reportedNodes.has(node.range.toString())) {
|
||||
const isPrivate = node.type === "PrivateIdentifier";
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: "restricted",
|
||||
messageId: isPrivate ? "restrictedPrivate" : "restricted",
|
||||
data: {
|
||||
name: node.name
|
||||
}
|
||||
});
|
||||
reportedNodes.add(node);
|
||||
reportedNodes.add(node.range.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,7 +214,10 @@ module.exports = {
|
|||
globalScope = context.getScope();
|
||||
},
|
||||
|
||||
Identifier(node) {
|
||||
[[
|
||||
"Identifier",
|
||||
"PrivateIdentifier"
|
||||
]](node) {
|
||||
if (isRestricted(node.name) && shouldCheck(node)) {
|
||||
report(node);
|
||||
}
|
||||
|
|
|
|||
91
node_modules/eslint/lib/rules/id-length.js
generated
vendored
91
node_modules/eslint/lib/rules/id-length.js
generated
vendored
|
|
@ -6,17 +6,56 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
const GraphemeSplitter = require("grapheme-splitter");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks if the string given as argument is ASCII or not.
|
||||
* @param {string} value A string that you want to know if it is ASCII or not.
|
||||
* @returns {boolean} `true` if `value` is ASCII string.
|
||||
*/
|
||||
function isASCII(value) {
|
||||
if (typeof value !== "string") {
|
||||
return false;
|
||||
}
|
||||
return /^[\u0020-\u007f]*$/u.test(value);
|
||||
}
|
||||
|
||||
/** @type {GraphemeSplitter | undefined} */
|
||||
let splitter;
|
||||
|
||||
/**
|
||||
* Gets the length of the string. If the string is not in ASCII, counts graphemes.
|
||||
* @param {string} value A string that you want to get the length.
|
||||
* @returns {number} The length of `value`.
|
||||
*/
|
||||
function getStringLength(value) {
|
||||
if (isASCII(value)) {
|
||||
return value.length;
|
||||
}
|
||||
if (!splitter) {
|
||||
splitter = new GraphemeSplitter();
|
||||
}
|
||||
return splitter.countGraphemes(value);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce minimum and maximum identifier lengths",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce minimum and maximum identifier lengths",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/id-length"
|
||||
},
|
||||
|
|
@ -55,7 +94,9 @@ module.exports = {
|
|||
],
|
||||
messages: {
|
||||
tooShort: "Identifier name '{{name}}' is too short (< {{min}}).",
|
||||
tooLong: "Identifier name '{{name}}' is too long (> {{max}})."
|
||||
tooShortPrivate: "Identifier name '#{{name}}' is too short (< {{min}}).",
|
||||
tooLong: "Identifier name '{{name}}' is too long (> {{max}}).",
|
||||
tooLongPrivate: "Identifier name #'{{name}}' is too long (> {{max}})."
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -66,7 +107,7 @@ module.exports = {
|
|||
const properties = options.properties !== "never";
|
||||
const exceptions = new Set(options.exceptions);
|
||||
const exceptionPatterns = (options.exceptionPatterns || []).map(pattern => new RegExp(pattern, "u"));
|
||||
const reportedNode = new Set();
|
||||
const reportedNodes = new Set();
|
||||
|
||||
/**
|
||||
* Checks if a string matches the provided exception patterns
|
||||
|
|
@ -99,12 +140,14 @@ module.exports = {
|
|||
Property(parent, node) {
|
||||
|
||||
if (parent.parent.type === "ObjectPattern") {
|
||||
const isKeyAndValueSame = parent.value.name === parent.key.name;
|
||||
|
||||
return (
|
||||
parent.value !== parent.key && parent.value === node ||
|
||||
parent.value === parent.key && parent.key === node && properties
|
||||
!isKeyAndValueSame && parent.value === node ||
|
||||
isKeyAndValueSame && parent.key === node && properties
|
||||
);
|
||||
}
|
||||
return properties && !parent.computed && parent.key === node;
|
||||
return properties && !parent.computed && parent.key.name === node.name;
|
||||
},
|
||||
ImportDefaultSpecifier: true,
|
||||
RestElement: true,
|
||||
|
|
@ -113,17 +156,23 @@ module.exports = {
|
|||
ClassDeclaration: true,
|
||||
FunctionDeclaration: true,
|
||||
MethodDefinition: true,
|
||||
PropertyDefinition: true,
|
||||
CatchClause: true,
|
||||
ArrayPattern: true
|
||||
};
|
||||
|
||||
return {
|
||||
Identifier(node) {
|
||||
[[
|
||||
"Identifier",
|
||||
"PrivateIdentifier"
|
||||
]](node) {
|
||||
const name = node.name;
|
||||
const parent = node.parent;
|
||||
|
||||
const isShort = name.length < minLength;
|
||||
const isLong = name.length > maxLength;
|
||||
const nameLength = getStringLength(name);
|
||||
|
||||
const isShort = nameLength < minLength;
|
||||
const isLong = nameLength > maxLength;
|
||||
|
||||
if (!(isShort || isLong) || exceptions.has(name) || matchesExceptionPattern(name)) {
|
||||
return; // Nothing to report
|
||||
|
|
@ -131,11 +180,27 @@ module.exports = {
|
|||
|
||||
const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type];
|
||||
|
||||
if (isValidExpression && !reportedNode.has(node) && (isValidExpression === true || isValidExpression(parent, node))) {
|
||||
reportedNode.add(node);
|
||||
/*
|
||||
* We used the range instead of the node because it's possible
|
||||
* for the same identifier to be represented by two different
|
||||
* nodes, with the most clear example being shorthand properties:
|
||||
* { foo }
|
||||
* In this case, "foo" is represented by one node for the name
|
||||
* and one for the value. The only way to know they are the same
|
||||
* is to look at the range.
|
||||
*/
|
||||
if (isValidExpression && !reportedNodes.has(node.range.toString()) && (isValidExpression === true || isValidExpression(parent, node))) {
|
||||
reportedNodes.add(node.range.toString());
|
||||
|
||||
let messageId = isShort ? "tooShort" : "tooLong";
|
||||
|
||||
if (node.type === "PrivateIdentifier") {
|
||||
messageId += "Private";
|
||||
}
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: isShort ? "tooShort" : "tooLong",
|
||||
messageId,
|
||||
data: { name, min: minLength, max: maxLength }
|
||||
});
|
||||
}
|
||||
|
|
|
|||
96
node_modules/eslint/lib/rules/id-match.js
generated
vendored
96
node_modules/eslint/lib/rules/id-match.js
generated
vendored
|
|
@ -9,13 +9,13 @@
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require identifiers to match a specified regular expression",
|
||||
category: "Stylistic Issues",
|
||||
description: "Require identifiers to match a specified regular expression",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/id-match"
|
||||
},
|
||||
|
|
@ -31,6 +31,10 @@ module.exports = {
|
|||
type: "boolean",
|
||||
default: false
|
||||
},
|
||||
classFields: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
},
|
||||
onlyDeclarations: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
|
|
@ -44,7 +48,8 @@ module.exports = {
|
|||
}
|
||||
],
|
||||
messages: {
|
||||
notMatch: "Identifier '{{name}}' does not match the pattern '{{pattern}}'."
|
||||
notMatch: "Identifier '{{name}}' does not match the pattern '{{pattern}}'.",
|
||||
notMatchPrivate: "Identifier '#{{name}}' does not match the pattern '{{pattern}}'."
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -57,20 +62,36 @@ module.exports = {
|
|||
regexp = new RegExp(pattern, "u");
|
||||
|
||||
const options = context.options[1] || {},
|
||||
properties = !!options.properties,
|
||||
checkProperties = !!options.properties,
|
||||
checkClassFields = !!options.classFields,
|
||||
onlyDeclarations = !!options.onlyDeclarations,
|
||||
ignoreDestructuring = !!options.ignoreDestructuring;
|
||||
|
||||
let globalScope;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// contains reported nodes to avoid reporting twice on destructuring with shorthand notation
|
||||
const reported = new Map();
|
||||
const reportedNodes = new Set();
|
||||
const ALLOWED_PARENT_TYPES = new Set(["CallExpression", "NewExpression"]);
|
||||
const DECLARATION_TYPES = new Set(["FunctionDeclaration", "VariableDeclarator"]);
|
||||
const IMPORT_TYPES = new Set(["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"]);
|
||||
|
||||
/**
|
||||
* Checks whether the given node represents a reference to a global variable that is not declared in the source code.
|
||||
* These identifiers will be allowed, as it is assumed that user has no control over the names of external global variables.
|
||||
* @param {ASTNode} node `Identifier` node to check.
|
||||
* @returns {boolean} `true` if the node is a reference to a global variable.
|
||||
*/
|
||||
function isReferenceToGlobalVariable(node) {
|
||||
const variable = globalScope.set.get(node.name);
|
||||
|
||||
return variable && variable.defs.length === 0 &&
|
||||
variable.references.some(ref => ref.identifier === node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a string matches the provided pattern
|
||||
* @param {string} name The string to check.
|
||||
|
|
@ -120,29 +141,51 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function report(node) {
|
||||
if (!reported.has(node)) {
|
||||
|
||||
/*
|
||||
* We used the range instead of the node because it's possible
|
||||
* for the same identifier to be represented by two different
|
||||
* nodes, with the most clear example being shorthand properties:
|
||||
* { foo }
|
||||
* In this case, "foo" is represented by one node for the name
|
||||
* and one for the value. The only way to know they are the same
|
||||
* is to look at the range.
|
||||
*/
|
||||
if (!reportedNodes.has(node.range.toString())) {
|
||||
|
||||
const messageId = (node.type === "PrivateIdentifier")
|
||||
? "notMatchPrivate" : "notMatch";
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: "notMatch",
|
||||
messageId,
|
||||
data: {
|
||||
name: node.name,
|
||||
pattern
|
||||
}
|
||||
});
|
||||
reported.set(node, true);
|
||||
reportedNodes.add(node.range.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Program() {
|
||||
globalScope = context.getScope();
|
||||
},
|
||||
|
||||
Identifier(node) {
|
||||
const name = node.name,
|
||||
parent = node.parent,
|
||||
effectiveParent = (parent.type === "MemberExpression") ? parent.parent : parent;
|
||||
|
||||
if (isReferenceToGlobalVariable(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent.type === "MemberExpression") {
|
||||
|
||||
if (!properties) {
|
||||
if (!checkProperties) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -168,6 +211,17 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
|
||||
// For https://github.com/eslint/eslint/issues/15123
|
||||
} else if (
|
||||
parent.type === "Property" &&
|
||||
parent.parent.type === "ObjectExpression" &&
|
||||
parent.key === node &&
|
||||
!parent.computed
|
||||
) {
|
||||
if (checkProperties && isInvalid(name)) {
|
||||
report(node);
|
||||
}
|
||||
|
||||
/*
|
||||
* Properties have their own rules, and
|
||||
* AssignmentPattern nodes can be treated like Properties:
|
||||
|
|
@ -176,8 +230,7 @@ module.exports = {
|
|||
} else if (parent.type === "Property" || parent.type === "AssignmentPattern") {
|
||||
|
||||
if (parent.parent && parent.parent.type === "ObjectPattern") {
|
||||
if (parent.shorthand && parent.value.left && isInvalid(name)) {
|
||||
|
||||
if (!ignoreDestructuring && parent.shorthand && parent.value.left && isInvalid(name)) {
|
||||
report(node);
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +250,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
// never check properties or always ignore destructuring
|
||||
if (!properties || (ignoreDestructuring && isInsideObjectPattern(node))) {
|
||||
if ((!checkProperties && !parent.computed) || (ignoreDestructuring && isInsideObjectPattern(node))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -214,10 +267,29 @@ module.exports = {
|
|||
report(node);
|
||||
}
|
||||
|
||||
} else if (parent.type === "PropertyDefinition") {
|
||||
|
||||
if (checkClassFields && isInvalid(name)) {
|
||||
report(node);
|
||||
}
|
||||
|
||||
// Report anything that is invalid that isn't a CallExpression
|
||||
} else if (shouldReport(effectiveParent, name)) {
|
||||
report(node);
|
||||
}
|
||||
},
|
||||
|
||||
"PrivateIdentifier"(node) {
|
||||
|
||||
const isClassField = node.parent.type === "PropertyDefinition";
|
||||
|
||||
if (isClassField && !checkClassFields) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInvalid(node.name)) {
|
||||
report(node);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/implicit-arrow-linebreak.js
generated
vendored
4
node_modules/eslint/lib/rules/implicit-arrow-linebreak.js
generated
vendored
|
|
@ -9,13 +9,13 @@ const { isCommentToken, isNotOpeningParenToken } = require("./utils/ast-utils");
|
|||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce the location of arrow function bodies",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce the location of arrow function bodies",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/implicit-arrow-linebreak"
|
||||
},
|
||||
|
|
|
|||
17
node_modules/eslint/lib/rules/indent-legacy.js
generated
vendored
17
node_modules/eslint/lib/rules/indent-legacy.js
generated
vendored
|
|
@ -4,6 +4,7 @@
|
|||
* This rule has been ported and modified from nodeca.
|
||||
* @author Vitaly Puzrin
|
||||
* @author Gyandeep Singh
|
||||
* @deprecated in ESLint v4.0.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
|
@ -17,15 +18,15 @@ const astUtils = require("./utils/ast-utils");
|
|||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* istanbul ignore next: this rule has known coverage issues, but it's deprecated and shouldn't be updated in the future anyway. */
|
||||
// this rule has known coverage issues, but it's deprecated and shouldn't be updated in the future anyway.
|
||||
/* c8 ignore next */
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent indentation",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce consistent indentation",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/indent-legacy"
|
||||
},
|
||||
|
|
@ -211,10 +212,10 @@ module.exports = {
|
|||
if (context.options[0] === "tab") {
|
||||
indentSize = 1;
|
||||
indentType = "tab";
|
||||
} else /* istanbul ignore else : this will be caught by options validation */ if (typeof context.options[0] === "number") {
|
||||
} else /* c8 ignore start */ if (typeof context.options[0] === "number") {
|
||||
indentSize = context.options[0];
|
||||
indentType = "space";
|
||||
}
|
||||
}/* c8 ignore stop */
|
||||
|
||||
if (context.options[1]) {
|
||||
const opts = context.options[1];
|
||||
|
|
@ -752,7 +753,7 @@ module.exports = {
|
|||
if (typeof options.CallExpression.arguments === "number") {
|
||||
nodeIndent += options.CallExpression.arguments * indentSize;
|
||||
} else if (options.CallExpression.arguments === "first") {
|
||||
if (parent.arguments.indexOf(node) !== -1) {
|
||||
if (parent.arguments.includes(node)) {
|
||||
nodeIndent = parent.arguments[0].loc.start.column;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -839,7 +840,7 @@ module.exports = {
|
|||
"IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration", "TryStatement"
|
||||
];
|
||||
|
||||
if (node.parent && statementsWithProperties.indexOf(node.parent.type) !== -1 && isNodeBodyBlock(node)) {
|
||||
if (node.parent && statementsWithProperties.includes(node.parent.type) && isNodeBodyBlock(node)) {
|
||||
indent = getNodeIndent(node.parent).goodChar;
|
||||
} else if (node.parent && node.parent.type === "CatchClause") {
|
||||
indent = getNodeIndent(node.parent.parent).goodChar;
|
||||
|
|
|
|||
180
node_modules/eslint/lib/rules/indent.js
generated
vendored
180
node_modules/eslint/lib/rules/indent.js
generated
vendored
|
|
@ -12,7 +12,7 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const createTree = require("functional-red-black-tree");
|
||||
const { OrderedMap } = require("js-sdsl");
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
|
|
@ -60,12 +60,15 @@ const KNOWN_NODES = new Set([
|
|||
"NewExpression",
|
||||
"ObjectExpression",
|
||||
"ObjectPattern",
|
||||
"PrivateIdentifier",
|
||||
"Program",
|
||||
"Property",
|
||||
"PropertyDefinition",
|
||||
"RestElement",
|
||||
"ReturnStatement",
|
||||
"SequenceExpression",
|
||||
"SpreadElement",
|
||||
"StaticBlock",
|
||||
"Super",
|
||||
"SwitchCase",
|
||||
"SwitchStatement",
|
||||
|
|
@ -132,23 +135,18 @@ class BinarySearchTree {
|
|||
* Creates an empty tree
|
||||
*/
|
||||
constructor() {
|
||||
this._rbTree = createTree();
|
||||
this._orderedMap = new OrderedMap();
|
||||
this._orderedMapEnd = this._orderedMap.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an entry into the tree.
|
||||
* @param {number} key The entry's key
|
||||
* @param {*} value The entry's value
|
||||
* @param {any} value The entry's value
|
||||
* @returns {void}
|
||||
*/
|
||||
insert(key, value) {
|
||||
const iterator = this._rbTree.find(key);
|
||||
|
||||
if (iterator.valid) {
|
||||
this._rbTree = iterator.update(value);
|
||||
} else {
|
||||
this._rbTree = this._rbTree.insert(key, value);
|
||||
}
|
||||
this._orderedMap.setElement(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -157,9 +155,13 @@ class BinarySearchTree {
|
|||
* @returns {{key: number, value: *}|null} The found entry, or null if no such entry exists.
|
||||
*/
|
||||
findLe(key) {
|
||||
const iterator = this._rbTree.le(key);
|
||||
const iterator = this._orderedMap.reverseLowerBound(key);
|
||||
|
||||
return iterator && { key: iterator.key, value: iterator.value };
|
||||
if (iterator.equals(this._orderedMapEnd)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return { key: iterator.pointer[0], value: iterator.pointer[1] };
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -174,11 +176,20 @@ class BinarySearchTree {
|
|||
if (start === end) {
|
||||
return;
|
||||
}
|
||||
const iterator = this._rbTree.ge(start);
|
||||
const iterator = this._orderedMap.lowerBound(start);
|
||||
|
||||
while (iterator.valid && iterator.key < end) {
|
||||
this._rbTree = this._rbTree.remove(iterator.key);
|
||||
iterator.next();
|
||||
if (iterator.equals(this._orderedMapEnd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (end > this._orderedMap.back()[0]) {
|
||||
while (!iterator.equals(this._orderedMapEnd)) {
|
||||
this._orderedMap.eraseElementByIterator(iterator);
|
||||
}
|
||||
} else {
|
||||
while (iterator.pointer[0] < end) {
|
||||
this._orderedMap.eraseElementByIterator(iterator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -188,7 +199,6 @@ class BinarySearchTree {
|
|||
*/
|
||||
class TokenInfo {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {SourceCode} sourceCode A SourceCode object
|
||||
*/
|
||||
|
|
@ -238,7 +248,6 @@ class TokenInfo {
|
|||
*/
|
||||
class OffsetStorage {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {TokenInfo} tokenInfo a TokenInfo instance
|
||||
* @param {number} indentSize The desired size of each indentation level
|
||||
|
|
@ -263,7 +272,7 @@ class OffsetStorage {
|
|||
|
||||
/**
|
||||
* Sets the offset column of token B to match the offset column of token A.
|
||||
* **WARNING**: This matches a *column*, even if baseToken is not the first token on its line. In
|
||||
* - **WARNING**: This matches a *column*, even if baseToken is not the first token on its line. In
|
||||
* most cases, `setDesiredOffset` should be used instead.
|
||||
* @param {Token} baseToken The first token
|
||||
* @param {Token} offsetToken The second token, whose offset should be matched to the first token
|
||||
|
|
@ -352,11 +361,11 @@ class OffsetStorage {
|
|||
* Instead, the offset tree is represented as a collection of contiguous offset ranges in a file. For example, the following
|
||||
* list could represent the state of the offset tree at a given point:
|
||||
*
|
||||
* * Tokens starting in the interval [0, 15) are aligned with the beginning of the file
|
||||
* * Tokens starting in the interval [15, 30) are offset by 1 indent level from the `bar` token
|
||||
* * Tokens starting in the interval [30, 43) are offset by 1 indent level from the `foo` token
|
||||
* * Tokens starting in the interval [43, 820) are offset by 2 indent levels from the `bar` token
|
||||
* * Tokens starting in the interval [820, ∞) are offset by 1 indent level from the `baz` token
|
||||
* - Tokens starting in the interval [0, 15) are aligned with the beginning of the file
|
||||
* - Tokens starting in the interval [15, 30) are offset by 1 indent level from the `bar` token
|
||||
* - Tokens starting in the interval [30, 43) are offset by 1 indent level from the `foo` token
|
||||
* - Tokens starting in the interval [43, 820) are offset by 2 indent levels from the `bar` token
|
||||
* - Tokens starting in the interval [820, ∞) are offset by 1 indent level from the `baz` token
|
||||
*
|
||||
* The `setDesiredOffsets` methods inserts ranges like the ones above. The third line above would be inserted by using:
|
||||
* `setDesiredOffsets([30, 43], fooToken, 1);`
|
||||
|
|
@ -493,13 +502,13 @@ const ELEMENT_LIST_SCHEMA = {
|
|||
]
|
||||
};
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent indentation",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce consistent indentation",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/indent"
|
||||
},
|
||||
|
|
@ -584,6 +593,16 @@ module.exports = {
|
|||
},
|
||||
additionalProperties: false
|
||||
},
|
||||
StaticBlock: {
|
||||
type: "object",
|
||||
properties: {
|
||||
body: {
|
||||
type: "integer",
|
||||
minimum: 0
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
},
|
||||
CallExpression: {
|
||||
type: "object",
|
||||
properties: {
|
||||
|
|
@ -647,6 +666,9 @@ module.exports = {
|
|||
parameters: DEFAULT_PARAMETER_INDENT,
|
||||
body: DEFAULT_FUNCTION_BODY_INDENT
|
||||
},
|
||||
StaticBlock: {
|
||||
body: DEFAULT_FUNCTION_BODY_INDENT
|
||||
},
|
||||
CallExpression: {
|
||||
arguments: DEFAULT_PARAMETER_INDENT
|
||||
},
|
||||
|
|
@ -782,7 +804,7 @@ module.exports = {
|
|||
let statement = node.parent && node.parent.parent;
|
||||
|
||||
while (
|
||||
statement.type === "UnaryExpression" && ["!", "~", "+", "-"].indexOf(statement.operator) > -1 ||
|
||||
statement.type === "UnaryExpression" && ["!", "~", "+", "-"].includes(statement.operator) ||
|
||||
statement.type === "AssignmentExpression" ||
|
||||
statement.type === "LogicalExpression" ||
|
||||
statement.type === "SequenceExpression" ||
|
||||
|
|
@ -902,18 +924,6 @@ module.exports = {
|
|||
}
|
||||
|
||||
offsets.setDesiredOffsets([firstBodyToken.range[0], lastBodyToken.range[1]], lastParentToken, 1);
|
||||
|
||||
/*
|
||||
* For blockless nodes with semicolon-first style, don't indent the semicolon.
|
||||
* e.g.
|
||||
* if (foo) bar()
|
||||
* ; [1, 2, 3].map(foo)
|
||||
*/
|
||||
const lastToken = sourceCode.getLastToken(node);
|
||||
|
||||
if (node.type !== "EmptyStatement" && astUtils.isSemicolonToken(lastToken)) {
|
||||
offsets.setDesiredOffset(lastToken, lastParentToken, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1209,7 +1219,7 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
|
||||
"DoWhileStatement, WhileStatement, ForInStatement, ForOfStatement": node => addBlocklessNodeIndent(node.body),
|
||||
"DoWhileStatement, WhileStatement, ForInStatement, ForOfStatement, WithStatement": node => addBlocklessNodeIndent(node.body),
|
||||
|
||||
ExportNamedDeclaration(node) {
|
||||
if (node.declaration === null) {
|
||||
|
|
@ -1257,6 +1267,50 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* For blockless nodes with semicolon-first style, don't indent the semicolon.
|
||||
* e.g.
|
||||
* if (foo)
|
||||
* bar()
|
||||
* ; [1, 2, 3].map(foo)
|
||||
*
|
||||
* Traversal into the node sets indentation of the semicolon, so we need to override it on exit.
|
||||
*/
|
||||
":matches(DoWhileStatement, ForStatement, ForInStatement, ForOfStatement, IfStatement, WhileStatement, WithStatement):exit"(node) {
|
||||
let nodesToCheck;
|
||||
|
||||
if (node.type === "IfStatement") {
|
||||
nodesToCheck = [node.consequent];
|
||||
if (node.alternate) {
|
||||
nodesToCheck.push(node.alternate);
|
||||
}
|
||||
} else {
|
||||
nodesToCheck = [node.body];
|
||||
}
|
||||
|
||||
for (const nodeToCheck of nodesToCheck) {
|
||||
const lastToken = sourceCode.getLastToken(nodeToCheck);
|
||||
|
||||
if (astUtils.isSemicolonToken(lastToken)) {
|
||||
const tokenBeforeLast = sourceCode.getTokenBefore(lastToken);
|
||||
const tokenAfterLast = sourceCode.getTokenAfter(lastToken);
|
||||
|
||||
// override indentation of `;` only if its line looks like a semicolon-first style line
|
||||
if (
|
||||
!astUtils.isTokenOnSameLine(tokenBeforeLast, lastToken) &&
|
||||
tokenAfterLast &&
|
||||
astUtils.isTokenOnSameLine(lastToken, tokenAfterLast)
|
||||
) {
|
||||
offsets.setDesiredOffset(
|
||||
lastToken,
|
||||
sourceCode.getFirstToken(node),
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ImportDeclaration(node) {
|
||||
if (node.specifiers.some(specifier => specifier.type === "ImportSpecifier")) {
|
||||
const openingCurly = sourceCode.getFirstToken(node, astUtils.isOpeningBraceToken);
|
||||
|
|
@ -1359,6 +1413,52 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
|
||||
PropertyDefinition(node) {
|
||||
const firstToken = sourceCode.getFirstToken(node);
|
||||
const maybeSemicolonToken = sourceCode.getLastToken(node);
|
||||
let keyLastToken = null;
|
||||
|
||||
// Indent key.
|
||||
if (node.computed) {
|
||||
const bracketTokenL = sourceCode.getTokenBefore(node.key, astUtils.isOpeningBracketToken);
|
||||
const bracketTokenR = keyLastToken = sourceCode.getTokenAfter(node.key, astUtils.isClosingBracketToken);
|
||||
const keyRange = [bracketTokenL.range[1], bracketTokenR.range[0]];
|
||||
|
||||
if (bracketTokenL !== firstToken) {
|
||||
offsets.setDesiredOffset(bracketTokenL, firstToken, 0);
|
||||
}
|
||||
offsets.setDesiredOffsets(keyRange, bracketTokenL, 1);
|
||||
offsets.setDesiredOffset(bracketTokenR, bracketTokenL, 0);
|
||||
} else {
|
||||
const idToken = keyLastToken = sourceCode.getFirstToken(node.key);
|
||||
|
||||
if (idToken !== firstToken) {
|
||||
offsets.setDesiredOffset(idToken, firstToken, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Indent initializer.
|
||||
if (node.value) {
|
||||
const eqToken = sourceCode.getTokenBefore(node.value, astUtils.isEqToken);
|
||||
const valueToken = sourceCode.getTokenAfter(eqToken);
|
||||
|
||||
offsets.setDesiredOffset(eqToken, keyLastToken, 1);
|
||||
offsets.setDesiredOffset(valueToken, eqToken, 1);
|
||||
if (astUtils.isSemicolonToken(maybeSemicolonToken)) {
|
||||
offsets.setDesiredOffset(maybeSemicolonToken, eqToken, 1);
|
||||
}
|
||||
} else if (astUtils.isSemicolonToken(maybeSemicolonToken)) {
|
||||
offsets.setDesiredOffset(maybeSemicolonToken, keyLastToken, 1);
|
||||
}
|
||||
},
|
||||
|
||||
StaticBlock(node) {
|
||||
const openingCurly = sourceCode.getFirstToken(node, { skip: 1 }); // skip the `static` token
|
||||
const closingCurly = sourceCode.getLastToken(node);
|
||||
|
||||
addElementListIndent(node.body, openingCurly, closingCurly, options.StaticBlock.body);
|
||||
},
|
||||
|
||||
SwitchStatement(node) {
|
||||
const openingCurly = sourceCode.getTokenAfter(node.discriminant, astUtils.isOpeningBraceToken);
|
||||
const closingCurly = sourceCode.getLastToken(node);
|
||||
|
|
|
|||
8
node_modules/eslint/lib/rules/index.js
generated
vendored
8
node_modules/eslint/lib/rules/index.js
generated
vendored
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint sort-keys: ["error", "asc"] */
|
||||
/* eslint sort-keys: ["error", "asc"] -- More readable for long list */
|
||||
|
||||
const { LazyLoadingRuleMap } = require("./utils/lazy-loading-rule-map");
|
||||
|
||||
|
|
@ -72,6 +72,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|||
"lines-around-comment": () => require("./lines-around-comment"),
|
||||
"lines-around-directive": () => require("./lines-around-directive"),
|
||||
"lines-between-class-members": () => require("./lines-between-class-members"),
|
||||
"logical-assignment-operators": () => require("./logical-assignment-operators"),
|
||||
"max-classes-per-file": () => require("./max-classes-per-file"),
|
||||
"max-depth": () => require("./max-depth"),
|
||||
"max-len": () => require("./max-len"),
|
||||
|
|
@ -103,6 +104,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|||
"no-confusing-arrow": () => require("./no-confusing-arrow"),
|
||||
"no-console": () => require("./no-console"),
|
||||
"no-const-assign": () => require("./no-const-assign"),
|
||||
"no-constant-binary-expression": () => require("./no-constant-binary-expression"),
|
||||
"no-constant-condition": () => require("./no-constant-condition"),
|
||||
"no-constructor-return": () => require("./no-constructor-return"),
|
||||
"no-continue": () => require("./no-continue"),
|
||||
|
|
@ -121,6 +123,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|||
"no-empty-character-class": () => require("./no-empty-character-class"),
|
||||
"no-empty-function": () => require("./no-empty-function"),
|
||||
"no-empty-pattern": () => require("./no-empty-pattern"),
|
||||
"no-empty-static-block": () => require("./no-empty-static-block"),
|
||||
"no-eq-null": () => require("./no-eq-null"),
|
||||
"no-eval": () => require("./no-eval"),
|
||||
"no-ex-assign": () => require("./no-ex-assign"),
|
||||
|
|
@ -165,6 +168,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|||
"no-nested-ternary": () => require("./no-nested-ternary"),
|
||||
"no-new": () => require("./no-new"),
|
||||
"no-new-func": () => require("./no-new-func"),
|
||||
"no-new-native-nonconstructor": () => require("./no-new-native-nonconstructor"),
|
||||
"no-new-object": () => require("./no-new-object"),
|
||||
"no-new-require": () => require("./no-new-require"),
|
||||
"no-new-symbol": () => require("./no-new-symbol"),
|
||||
|
|
@ -221,6 +225,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|||
"no-unsafe-optional-chaining": () => require("./no-unsafe-optional-chaining"),
|
||||
"no-unused-expressions": () => require("./no-unused-expressions"),
|
||||
"no-unused-labels": () => require("./no-unused-labels"),
|
||||
"no-unused-private-class-members": () => require("./no-unused-private-class-members"),
|
||||
"no-unused-vars": () => require("./no-unused-vars"),
|
||||
"no-use-before-define": () => require("./no-use-before-define"),
|
||||
"no-useless-backreference": () => require("./no-useless-backreference"),
|
||||
|
|
@ -254,6 +259,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|||
"prefer-exponentiation-operator": () => require("./prefer-exponentiation-operator"),
|
||||
"prefer-named-capture-group": () => require("./prefer-named-capture-group"),
|
||||
"prefer-numeric-literals": () => require("./prefer-numeric-literals"),
|
||||
"prefer-object-has-own": () => require("./prefer-object-has-own"),
|
||||
"prefer-object-spread": () => require("./prefer-object-spread"),
|
||||
"prefer-promise-reject-errors": () => require("./prefer-promise-reject-errors"),
|
||||
"prefer-reflect": () => require("./prefer-reflect"),
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/init-declarations.js
generated
vendored
4
node_modules/eslint/lib/rules/init-declarations.js
generated
vendored
|
|
@ -42,13 +42,13 @@ function isInitialized(node) {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "require or disallow initialization in variable declarations",
|
||||
category: "Variables",
|
||||
description: "Require or disallow initialization in variable declarations",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/init-declarations"
|
||||
},
|
||||
|
|
|
|||
6
node_modules/eslint/lib/rules/jsx-quotes.js
generated
vendored
6
node_modules/eslint/lib/rules/jsx-quotes.js
generated
vendored
|
|
@ -36,13 +36,13 @@ const QUOTE_SETTINGS = {
|
|||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce the consistent use of either double or single quotes in JSX attributes",
|
||||
category: "Stylistic Issues",
|
||||
description: "Enforce the consistent use of either double or single quotes in JSX attributes",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/jsx-quotes"
|
||||
},
|
||||
|
|
@ -70,7 +70,7 @@ module.exports = {
|
|||
* @public
|
||||
*/
|
||||
function usesExpectedQuotes(node) {
|
||||
return node.value.indexOf(setting.quote) !== -1 || astUtils.isSurroundedBy(node.raw, setting.quote);
|
||||
return node.value.includes(setting.quote) || astUtils.isSurroundedBy(node.raw, setting.quote);
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue