Update checked-in dependencies
This commit is contained in:
parent
6b0d45a5c6
commit
cc1adb825a
4247 changed files with 144820 additions and 149530 deletions
502
node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js
generated
vendored
502
node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js
generated
vendored
|
|
@ -1,502 +0,0 @@
|
|||
/*
|
||||
* STOP!!! DO NOT MODIFY.
|
||||
*
|
||||
* This file is part of the ongoing work to move the eslintrc-style config
|
||||
* system into the @eslint/eslintrc package. This file needs to remain
|
||||
* unchanged in order for this work to proceed.
|
||||
*
|
||||
* If you think you need to change this file, please contact @nzakas first.
|
||||
*
|
||||
* Thanks in advance for your cooperation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview `CascadingConfigArrayFactory` class.
|
||||
*
|
||||
* `CascadingConfigArrayFactory` class has a responsibility:
|
||||
*
|
||||
* 1. Handles cascading of config files.
|
||||
*
|
||||
* It provides two methods:
|
||||
*
|
||||
* - `getConfigArrayForFile(filePath)`
|
||||
* Get the corresponded configuration of a given file. This method doesn't
|
||||
* throw even if the given file didn't exist.
|
||||
* - `clearCache()`
|
||||
* Clear the internal cache. You have to call this method when
|
||||
* `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends
|
||||
* on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)
|
||||
*
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
const { validateConfigArray } = require("../shared/config-validator");
|
||||
const { emitDeprecationWarning } = require("../shared/deprecation-warnings");
|
||||
const { ConfigArrayFactory } = require("./config-array-factory");
|
||||
const { ConfigArray, ConfigDependency, IgnorePattern } = require("./config-array");
|
||||
const loadRules = require("./load-rules");
|
||||
const debug = require("debug")("eslint:cascading-config-array-factory");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Define types for VSCode IntelliSense.
|
||||
/** @typedef {import("../shared/types").ConfigData} ConfigData */
|
||||
/** @typedef {import("../shared/types").Parser} Parser */
|
||||
/** @typedef {import("../shared/types").Plugin} Plugin */
|
||||
/** @typedef {ReturnType<ConfigArrayFactory["create"]>} ConfigArray */
|
||||
|
||||
/**
|
||||
* @typedef {Object} CascadingConfigArrayFactoryOptions
|
||||
* @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
|
||||
* @property {ConfigData} [baseConfig] The config by `baseConfig` option.
|
||||
* @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.
|
||||
* @property {string} [cwd] The base directory to start lookup.
|
||||
* @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
|
||||
* @property {string[]} [rulePaths] The value of `--rulesdir` option.
|
||||
* @property {string} [specificConfigPath] The value of `--config` option.
|
||||
* @property {boolean} [useEslintrc] if `false` then it doesn't load config files.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} CascadingConfigArrayFactoryInternalSlots
|
||||
* @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.
|
||||
* @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.
|
||||
* @property {ConfigArray} cliConfigArray The config array of CLI options.
|
||||
* @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.
|
||||
* @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.
|
||||
* @property {Map<string, ConfigArray>} configCache The cache from directory paths to config arrays.
|
||||
* @property {string} cwd The base directory to start lookup.
|
||||
* @property {WeakMap<ConfigArray, ConfigArray>} finalizeCache The cache from config arrays to finalized config arrays.
|
||||
* @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
|
||||
* @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.
|
||||
* @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.
|
||||
* @property {boolean} useEslintrc if `false` then it doesn't load config files.
|
||||
*/
|
||||
|
||||
/** @type {WeakMap<CascadingConfigArrayFactory, CascadingConfigArrayFactoryInternalSlots>} */
|
||||
const internalSlotsMap = new WeakMap();
|
||||
|
||||
/**
|
||||
* Create the config array from `baseConfig` and `rulePaths`.
|
||||
* @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
|
||||
* @returns {ConfigArray} The config array of the base configs.
|
||||
*/
|
||||
function createBaseConfigArray({
|
||||
configArrayFactory,
|
||||
baseConfigData,
|
||||
rulePaths,
|
||||
cwd
|
||||
}) {
|
||||
const baseConfigArray = configArrayFactory.create(
|
||||
baseConfigData,
|
||||
{ name: "BaseConfig" }
|
||||
);
|
||||
|
||||
/*
|
||||
* Create the config array element for the default ignore patterns.
|
||||
* This element has `ignorePattern` property that ignores the default
|
||||
* patterns in the current working directory.
|
||||
*/
|
||||
baseConfigArray.unshift(configArrayFactory.create(
|
||||
{ ignorePatterns: IgnorePattern.DefaultPatterns },
|
||||
{ name: "DefaultIgnorePattern" }
|
||||
)[0]);
|
||||
|
||||
/*
|
||||
* Load rules `--rulesdir` option as a pseudo plugin.
|
||||
* Use a pseudo plugin to define rules of `--rulesdir`, so we can validate
|
||||
* the rule's options with only information in the config array.
|
||||
*/
|
||||
if (rulePaths && rulePaths.length > 0) {
|
||||
baseConfigArray.push({
|
||||
type: "config",
|
||||
name: "--rulesdir",
|
||||
filePath: "",
|
||||
plugins: {
|
||||
"": new ConfigDependency({
|
||||
definition: {
|
||||
rules: rulePaths.reduce(
|
||||
(map, rulesPath) => Object.assign(
|
||||
map,
|
||||
loadRules(rulesPath, cwd)
|
||||
),
|
||||
{}
|
||||
)
|
||||
},
|
||||
filePath: "",
|
||||
id: "",
|
||||
importerName: "--rulesdir",
|
||||
importerPath: ""
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return baseConfigArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the config array from CLI options.
|
||||
* @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
|
||||
* @returns {ConfigArray} The config array of the base configs.
|
||||
*/
|
||||
function createCLIConfigArray({
|
||||
cliConfigData,
|
||||
configArrayFactory,
|
||||
cwd,
|
||||
ignorePath,
|
||||
specificConfigPath
|
||||
}) {
|
||||
const cliConfigArray = configArrayFactory.create(
|
||||
cliConfigData,
|
||||
{ name: "CLIOptions" }
|
||||
);
|
||||
|
||||
cliConfigArray.unshift(
|
||||
...(ignorePath
|
||||
? configArrayFactory.loadESLintIgnore(ignorePath)
|
||||
: configArrayFactory.loadDefaultESLintIgnore())
|
||||
);
|
||||
|
||||
if (specificConfigPath) {
|
||||
cliConfigArray.unshift(
|
||||
...configArrayFactory.loadFile(
|
||||
specificConfigPath,
|
||||
{ name: "--config", basePath: cwd }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return cliConfigArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* The error type when there are files matched by a glob, but all of them have been ignored.
|
||||
*/
|
||||
class ConfigurationNotFoundError extends Error {
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {string} directoryPath The directory path.
|
||||
*/
|
||||
constructor(directoryPath) {
|
||||
super(`No ESLint configuration found in ${directoryPath}.`);
|
||||
this.messageTemplate = "no-config-found";
|
||||
this.messageData = { directoryPath };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class provides the functionality that enumerates every file which is
|
||||
* matched by given glob patterns and that configuration.
|
||||
*/
|
||||
class CascadingConfigArrayFactory {
|
||||
|
||||
/**
|
||||
* Initialize this enumerator.
|
||||
* @param {CascadingConfigArrayFactoryOptions} options The options.
|
||||
*/
|
||||
constructor({
|
||||
additionalPluginPool = new Map(),
|
||||
baseConfig: baseConfigData = null,
|
||||
cliConfig: cliConfigData = null,
|
||||
cwd = process.cwd(),
|
||||
ignorePath,
|
||||
resolvePluginsRelativeTo,
|
||||
rulePaths = [],
|
||||
specificConfigPath = null,
|
||||
useEslintrc = true
|
||||
} = {}) {
|
||||
const configArrayFactory = new ConfigArrayFactory({
|
||||
additionalPluginPool,
|
||||
cwd,
|
||||
resolvePluginsRelativeTo
|
||||
});
|
||||
|
||||
internalSlotsMap.set(this, {
|
||||
baseConfigArray: createBaseConfigArray({
|
||||
baseConfigData,
|
||||
configArrayFactory,
|
||||
cwd,
|
||||
rulePaths
|
||||
}),
|
||||
baseConfigData,
|
||||
cliConfigArray: createCLIConfigArray({
|
||||
cliConfigData,
|
||||
configArrayFactory,
|
||||
cwd,
|
||||
ignorePath,
|
||||
specificConfigPath
|
||||
}),
|
||||
cliConfigData,
|
||||
configArrayFactory,
|
||||
configCache: new Map(),
|
||||
cwd,
|
||||
finalizeCache: new WeakMap(),
|
||||
ignorePath,
|
||||
rulePaths,
|
||||
specificConfigPath,
|
||||
useEslintrc
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The path to the current working directory.
|
||||
* This is used by tests.
|
||||
* @type {string}
|
||||
*/
|
||||
get cwd() {
|
||||
const { cwd } = internalSlotsMap.get(this);
|
||||
|
||||
return cwd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config array of a given file.
|
||||
* If `filePath` was not given, it returns the config which contains only
|
||||
* `baseConfigData` and `cliConfigData`.
|
||||
* @param {string} [filePath] The file path to a file.
|
||||
* @param {Object} [options] The options.
|
||||
* @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.
|
||||
* @returns {ConfigArray} The config array of the file.
|
||||
*/
|
||||
getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {
|
||||
const {
|
||||
baseConfigArray,
|
||||
cliConfigArray,
|
||||
cwd
|
||||
} = internalSlotsMap.get(this);
|
||||
|
||||
if (!filePath) {
|
||||
return new ConfigArray(...baseConfigArray, ...cliConfigArray);
|
||||
}
|
||||
|
||||
const directoryPath = path.dirname(path.resolve(cwd, filePath));
|
||||
|
||||
debug(`Load config files for ${directoryPath}.`);
|
||||
|
||||
return this._finalizeConfigArray(
|
||||
this._loadConfigInAncestors(directoryPath),
|
||||
directoryPath,
|
||||
ignoreNotFoundError
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the config data to override all configs.
|
||||
* Require to call `clearCache()` method after this method is called.
|
||||
* @param {ConfigData} configData The config data to override all configs.
|
||||
* @returns {void}
|
||||
*/
|
||||
setOverrideConfig(configData) {
|
||||
const slots = internalSlotsMap.get(this);
|
||||
|
||||
slots.cliConfigData = configData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear config cache.
|
||||
* @returns {void}
|
||||
*/
|
||||
clearCache() {
|
||||
const slots = internalSlotsMap.get(this);
|
||||
|
||||
slots.baseConfigArray = createBaseConfigArray(slots);
|
||||
slots.cliConfigArray = createCLIConfigArray(slots);
|
||||
slots.configCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and normalize config files from the ancestor directories.
|
||||
* @param {string} directoryPath The path to a leaf directory.
|
||||
* @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
|
||||
* @returns {ConfigArray} The loaded config.
|
||||
* @private
|
||||
*/
|
||||
_loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
|
||||
const {
|
||||
baseConfigArray,
|
||||
configArrayFactory,
|
||||
configCache,
|
||||
cwd,
|
||||
useEslintrc
|
||||
} = internalSlotsMap.get(this);
|
||||
|
||||
if (!useEslintrc) {
|
||||
return baseConfigArray;
|
||||
}
|
||||
|
||||
let configArray = configCache.get(directoryPath);
|
||||
|
||||
// Hit cache.
|
||||
if (configArray) {
|
||||
debug(`Cache hit: ${directoryPath}.`);
|
||||
return configArray;
|
||||
}
|
||||
debug(`No cache found: ${directoryPath}.`);
|
||||
|
||||
const homePath = os.homedir();
|
||||
|
||||
// Consider this is root.
|
||||
if (directoryPath === homePath && cwd !== homePath) {
|
||||
debug("Stop traversing because of considered root.");
|
||||
if (configsExistInSubdirs) {
|
||||
const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);
|
||||
|
||||
if (filePath) {
|
||||
emitDeprecationWarning(
|
||||
filePath,
|
||||
"ESLINT_PERSONAL_CONFIG_SUPPRESS"
|
||||
);
|
||||
}
|
||||
}
|
||||
return this._cacheConfig(directoryPath, baseConfigArray);
|
||||
}
|
||||
|
||||
// Load the config on this directory.
|
||||
try {
|
||||
configArray = configArrayFactory.loadInDirectory(directoryPath);
|
||||
} catch (error) {
|
||||
/* istanbul ignore next */
|
||||
if (error.code === "EACCES") {
|
||||
debug("Stop traversing because of 'EACCES' error.");
|
||||
return this._cacheConfig(directoryPath, baseConfigArray);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (configArray.length > 0 && configArray.isRoot()) {
|
||||
debug("Stop traversing because of 'root:true'.");
|
||||
configArray.unshift(...baseConfigArray);
|
||||
return this._cacheConfig(directoryPath, configArray);
|
||||
}
|
||||
|
||||
// Load from the ancestors and merge it.
|
||||
const parentPath = path.dirname(directoryPath);
|
||||
const parentConfigArray = parentPath && parentPath !== directoryPath
|
||||
? this._loadConfigInAncestors(
|
||||
parentPath,
|
||||
configsExistInSubdirs || configArray.length > 0
|
||||
)
|
||||
: baseConfigArray;
|
||||
|
||||
if (configArray.length > 0) {
|
||||
configArray.unshift(...parentConfigArray);
|
||||
} else {
|
||||
configArray = parentConfigArray;
|
||||
}
|
||||
|
||||
// Cache and return.
|
||||
return this._cacheConfig(directoryPath, configArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze and cache a given config.
|
||||
* @param {string} directoryPath The path to a directory as a cache key.
|
||||
* @param {ConfigArray} configArray The config array as a cache value.
|
||||
* @returns {ConfigArray} The `configArray` (frozen).
|
||||
*/
|
||||
_cacheConfig(directoryPath, configArray) {
|
||||
const { configCache } = internalSlotsMap.get(this);
|
||||
|
||||
Object.freeze(configArray);
|
||||
configCache.set(directoryPath, configArray);
|
||||
|
||||
return configArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize a given config array.
|
||||
* Concatenate `--config` and other CLI options.
|
||||
* @param {ConfigArray} configArray The parent config array.
|
||||
* @param {string} directoryPath The path to the leaf directory to find config files.
|
||||
* @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.
|
||||
* @returns {ConfigArray} The loaded config.
|
||||
* @private
|
||||
*/
|
||||
_finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {
|
||||
const {
|
||||
cliConfigArray,
|
||||
configArrayFactory,
|
||||
finalizeCache,
|
||||
useEslintrc
|
||||
} = internalSlotsMap.get(this);
|
||||
|
||||
let finalConfigArray = finalizeCache.get(configArray);
|
||||
|
||||
if (!finalConfigArray) {
|
||||
finalConfigArray = configArray;
|
||||
|
||||
// Load the personal config if there are no regular config files.
|
||||
if (
|
||||
useEslintrc &&
|
||||
configArray.every(c => !c.filePath) &&
|
||||
cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.
|
||||
) {
|
||||
const homePath = os.homedir();
|
||||
|
||||
debug("Loading the config file of the home directory:", homePath);
|
||||
|
||||
const personalConfigArray = configArrayFactory.loadInDirectory(
|
||||
homePath,
|
||||
{ name: "PersonalConfig" }
|
||||
);
|
||||
|
||||
if (
|
||||
personalConfigArray.length > 0 &&
|
||||
!directoryPath.startsWith(homePath)
|
||||
) {
|
||||
const lastElement =
|
||||
personalConfigArray[personalConfigArray.length - 1];
|
||||
|
||||
emitDeprecationWarning(
|
||||
lastElement.filePath,
|
||||
"ESLINT_PERSONAL_CONFIG_LOAD"
|
||||
);
|
||||
}
|
||||
|
||||
finalConfigArray = finalConfigArray.concat(personalConfigArray);
|
||||
}
|
||||
|
||||
// Apply CLI options.
|
||||
if (cliConfigArray.length > 0) {
|
||||
finalConfigArray = finalConfigArray.concat(cliConfigArray);
|
||||
}
|
||||
|
||||
// Validate rule settings and environments.
|
||||
validateConfigArray(finalConfigArray);
|
||||
|
||||
// Cache it.
|
||||
Object.freeze(finalConfigArray);
|
||||
finalizeCache.set(configArray, finalConfigArray);
|
||||
|
||||
debug(
|
||||
"Configuration was determined: %o on %s",
|
||||
finalConfigArray,
|
||||
directoryPath
|
||||
);
|
||||
}
|
||||
|
||||
// At least one element (the default ignore patterns) exists.
|
||||
if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {
|
||||
throw new ConfigurationNotFoundError(directoryPath);
|
||||
}
|
||||
|
||||
return finalConfigArray;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = { CascadingConfigArrayFactory };
|
||||
32
node_modules/eslint/lib/cli-engine/cli-engine.js
generated
vendored
32
node_modules/eslint/lib/cli-engine/cli-engine.js
generated
vendored
|
|
@ -19,14 +19,24 @@ const fs = require("fs");
|
|||
const path = require("path");
|
||||
const defaultOptions = require("../../conf/default-cli-options");
|
||||
const pkg = require("../../package.json");
|
||||
const ConfigOps = require("@eslint/eslintrc/lib/shared/config-ops");
|
||||
const naming = require("@eslint/eslintrc/lib/shared/naming");
|
||||
const ModuleResolver = require("../shared/relative-module-resolver");
|
||||
|
||||
|
||||
const {
|
||||
Legacy: {
|
||||
ConfigOps,
|
||||
naming,
|
||||
CascadingConfigArrayFactory,
|
||||
IgnorePattern,
|
||||
getUsedExtractedConfigs,
|
||||
ModuleResolver
|
||||
}
|
||||
} = require("@eslint/eslintrc");
|
||||
|
||||
const { FileEnumerator } = require("./file-enumerator");
|
||||
|
||||
const { Linter } = require("../linter");
|
||||
const builtInRules = require("../rules");
|
||||
const { CascadingConfigArrayFactory } = require("./cascading-config-array-factory");
|
||||
const { IgnorePattern, getUsedExtractedConfigs } = require("./config-array");
|
||||
const { FileEnumerator } = require("./file-enumerator");
|
||||
const loadRules = require("./load-rules");
|
||||
const hash = require("./hash");
|
||||
const LintResultCache = require("./lint-result-cache");
|
||||
|
||||
|
|
@ -516,7 +526,7 @@ function directoryExists(resolvedPath) {
|
|||
try {
|
||||
return fs.statSync(resolvedPath).isDirectory();
|
||||
} catch (error) {
|
||||
if (error && error.code === "ENOENT") {
|
||||
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
||||
return false;
|
||||
}
|
||||
throw error;
|
||||
|
|
@ -559,7 +569,11 @@ class CLIEngine {
|
|||
resolvePluginsRelativeTo: options.resolvePluginsRelativeTo,
|
||||
rulePaths: options.rulePaths,
|
||||
specificConfigPath: options.configFile,
|
||||
useEslintrc: options.useEslintrc
|
||||
useEslintrc: options.useEslintrc,
|
||||
builtInRules,
|
||||
loadRules,
|
||||
eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
|
||||
eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
|
||||
});
|
||||
const fileEnumerator = new FileEnumerator({
|
||||
configArrayFactory,
|
||||
|
|
@ -570,7 +584,7 @@ class CLIEngine {
|
|||
ignore: options.ignore
|
||||
});
|
||||
const lintResultCache =
|
||||
options.cache ? new LintResultCache(cacheFilePath) : null;
|
||||
options.cache ? new LintResultCache(cacheFilePath, options.cacheStrategy) : null;
|
||||
const linter = new Linter({ cwd: options.cwd });
|
||||
|
||||
/** @type {ConfigArray[]} */
|
||||
|
|
|
|||
1092
node_modules/eslint/lib/cli-engine/config-array-factory.js
generated
vendored
1092
node_modules/eslint/lib/cli-engine/config-array-factory.js
generated
vendored
File diff suppressed because it is too large
Load diff
536
node_modules/eslint/lib/cli-engine/config-array/config-array.js
generated
vendored
536
node_modules/eslint/lib/cli-engine/config-array/config-array.js
generated
vendored
|
|
@ -1,536 +0,0 @@
|
|||
/*
|
||||
* STOP!!! DO NOT MODIFY.
|
||||
*
|
||||
* This file is part of the ongoing work to move the eslintrc-style config
|
||||
* system into the @eslint/eslintrc package. This file needs to remain
|
||||
* unchanged in order for this work to proceed.
|
||||
*
|
||||
* If you think you need to change this file, please contact @nzakas first.
|
||||
*
|
||||
* Thanks in advance for your cooperation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview `ConfigArray` class.
|
||||
*
|
||||
* `ConfigArray` class expresses the full of a configuration. It has the entry
|
||||
* config file, base config files that were extended, loaded parsers, and loaded
|
||||
* plugins.
|
||||
*
|
||||
* `ConfigArray` class provides three properties and two methods.
|
||||
*
|
||||
* - `pluginEnvironments`
|
||||
* - `pluginProcessors`
|
||||
* - `pluginRules`
|
||||
* The `Map` objects that contain the members of all plugins that this
|
||||
* config array contains. Those map objects don't have mutation methods.
|
||||
* Those keys are the member ID such as `pluginId/memberName`.
|
||||
* - `isRoot()`
|
||||
* If `true` then this configuration has `root:true` property.
|
||||
* - `extractConfig(filePath)`
|
||||
* Extract the final configuration for a given file. This means merging
|
||||
* every config array element which that `criteria` property matched. The
|
||||
* `filePath` argument must be an absolute path.
|
||||
*
|
||||
* `ConfigArrayFactory` provides the loading logic of config files.
|
||||
*
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const { ExtractedConfig } = require("./extracted-config");
|
||||
const { IgnorePattern } = require("./ignore-pattern");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Define types for VSCode IntelliSense.
|
||||
/** @typedef {import("../../shared/types").Environment} Environment */
|
||||
/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
|
||||
/** @typedef {import("../../shared/types").RuleConf} RuleConf */
|
||||
/** @typedef {import("../../shared/types").Rule} Rule */
|
||||
/** @typedef {import("../../shared/types").Plugin} Plugin */
|
||||
/** @typedef {import("../../shared/types").Processor} Processor */
|
||||
/** @typedef {import("./config-dependency").DependentParser} DependentParser */
|
||||
/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
|
||||
/** @typedef {import("./override-tester")["OverrideTester"]} OverrideTester */
|
||||
|
||||
/**
|
||||
* @typedef {Object} ConfigArrayElement
|
||||
* @property {string} name The name of this config element.
|
||||
* @property {string} filePath The path to the source file of this config element.
|
||||
* @property {InstanceType<OverrideTester>|null} criteria The tester for the `files` and `excludedFiles` of this config element.
|
||||
* @property {Record<string, boolean>|undefined} env The environment settings.
|
||||
* @property {Record<string, GlobalConf>|undefined} globals The global variable settings.
|
||||
* @property {IgnorePattern|undefined} ignorePattern The ignore patterns.
|
||||
* @property {boolean|undefined} noInlineConfig The flag that disables directive comments.
|
||||
* @property {DependentParser|undefined} parser The parser loader.
|
||||
* @property {Object|undefined} parserOptions The parser options.
|
||||
* @property {Record<string, DependentPlugin>|undefined} plugins The plugin loaders.
|
||||
* @property {string|undefined} processor The processor name to refer plugin's processor.
|
||||
* @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.
|
||||
* @property {boolean|undefined} root The flag to express root.
|
||||
* @property {Record<string, RuleConf>|undefined} rules The rule settings
|
||||
* @property {Object|undefined} settings The shared settings.
|
||||
* @property {"config" | "ignore" | "implicit-processor"} type The element type.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ConfigArrayInternalSlots
|
||||
* @property {Map<string, ExtractedConfig>} cache The cache to extract configs.
|
||||
* @property {ReadonlyMap<string, Environment>|null} envMap The map from environment ID to environment definition.
|
||||
* @property {ReadonlyMap<string, Processor>|null} processorMap The map from processor ID to environment definition.
|
||||
* @property {ReadonlyMap<string, Rule>|null} ruleMap The map from rule ID to rule definition.
|
||||
*/
|
||||
|
||||
/** @type {WeakMap<ConfigArray, ConfigArrayInternalSlots>} */
|
||||
const internalSlotsMap = new class extends WeakMap {
|
||||
get(key) {
|
||||
let value = super.get(key);
|
||||
|
||||
if (!value) {
|
||||
value = {
|
||||
cache: new Map(),
|
||||
envMap: null,
|
||||
processorMap: null,
|
||||
ruleMap: null
|
||||
};
|
||||
super.set(key, value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}();
|
||||
|
||||
/**
|
||||
* Get the indices which are matched to a given file.
|
||||
* @param {ConfigArrayElement[]} elements The elements.
|
||||
* @param {string} filePath The path to a target file.
|
||||
* @returns {number[]} The indices.
|
||||
*/
|
||||
function getMatchedIndices(elements, filePath) {
|
||||
const indices = [];
|
||||
|
||||
for (let i = elements.length - 1; i >= 0; --i) {
|
||||
const element = elements[i];
|
||||
|
||||
if (!element.criteria || (filePath && element.criteria.test(filePath))) {
|
||||
indices.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a value is a non-null object.
|
||||
* @param {any} x The value to check.
|
||||
* @returns {boolean} `true` if the value is a non-null object.
|
||||
*/
|
||||
function isNonNullObject(x) {
|
||||
return typeof x === "object" && x !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two objects.
|
||||
*
|
||||
* Assign every property values of `y` to `x` if `x` doesn't have the property.
|
||||
* If `x`'s property value is an object, it does recursive.
|
||||
* @param {Object} target The destination to merge
|
||||
* @param {Object|undefined} source The source to merge.
|
||||
* @returns {void}
|
||||
*/
|
||||
function mergeWithoutOverwrite(target, source) {
|
||||
if (!isNonNullObject(source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(source)) {
|
||||
if (key === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isNonNullObject(target[key])) {
|
||||
mergeWithoutOverwrite(target[key], source[key]);
|
||||
} else if (target[key] === void 0) {
|
||||
if (isNonNullObject(source[key])) {
|
||||
target[key] = Array.isArray(source[key]) ? [] : {};
|
||||
mergeWithoutOverwrite(target[key], source[key]);
|
||||
} else if (source[key] !== void 0) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The error for plugin conflicts.
|
||||
*/
|
||||
class PluginConflictError extends Error {
|
||||
|
||||
/**
|
||||
* Initialize this error object.
|
||||
* @param {string} pluginId The plugin ID.
|
||||
* @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.
|
||||
*/
|
||||
constructor(pluginId, plugins) {
|
||||
super(`Plugin "${pluginId}" was conflicted between ${plugins.map(p => `"${p.importerName}"`).join(" and ")}.`);
|
||||
this.messageTemplate = "plugin-conflict";
|
||||
this.messageData = { pluginId, plugins };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge plugins.
|
||||
* `target`'s definition is prior to `source`'s.
|
||||
* @param {Record<string, DependentPlugin>} target The destination to merge
|
||||
* @param {Record<string, DependentPlugin>|undefined} source The source to merge.
|
||||
* @returns {void}
|
||||
*/
|
||||
function mergePlugins(target, source) {
|
||||
if (!isNonNullObject(source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(source)) {
|
||||
if (key === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
const targetValue = target[key];
|
||||
const sourceValue = source[key];
|
||||
|
||||
// Adopt the plugin which was found at first.
|
||||
if (targetValue === void 0) {
|
||||
if (sourceValue.error) {
|
||||
throw sourceValue.error;
|
||||
}
|
||||
target[key] = sourceValue;
|
||||
} else if (sourceValue.filePath !== targetValue.filePath) {
|
||||
throw new PluginConflictError(key, [
|
||||
{
|
||||
filePath: targetValue.filePath,
|
||||
importerName: targetValue.importerName
|
||||
},
|
||||
{
|
||||
filePath: sourceValue.filePath,
|
||||
importerName: sourceValue.importerName
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge rule configs.
|
||||
* `target`'s definition is prior to `source`'s.
|
||||
* @param {Record<string, Array>} target The destination to merge
|
||||
* @param {Record<string, RuleConf>|undefined} source The source to merge.
|
||||
* @returns {void}
|
||||
*/
|
||||
function mergeRuleConfigs(target, source) {
|
||||
if (!isNonNullObject(source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(source)) {
|
||||
if (key === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
const targetDef = target[key];
|
||||
const sourceDef = source[key];
|
||||
|
||||
// Adopt the rule config which was found at first.
|
||||
if (targetDef === void 0) {
|
||||
if (Array.isArray(sourceDef)) {
|
||||
target[key] = [...sourceDef];
|
||||
} else {
|
||||
target[key] = [sourceDef];
|
||||
}
|
||||
|
||||
/*
|
||||
* If the first found rule config is severity only and the current rule
|
||||
* config has options, merge the severity and the options.
|
||||
*/
|
||||
} else if (
|
||||
targetDef.length === 1 &&
|
||||
Array.isArray(sourceDef) &&
|
||||
sourceDef.length >= 2
|
||||
) {
|
||||
targetDef.push(...sourceDef.slice(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the extracted config.
|
||||
* @param {ConfigArray} instance The config elements.
|
||||
* @param {number[]} indices The indices to use.
|
||||
* @returns {ExtractedConfig} The extracted config.
|
||||
*/
|
||||
function createConfig(instance, indices) {
|
||||
const config = new ExtractedConfig();
|
||||
const ignorePatterns = [];
|
||||
|
||||
// Merge elements.
|
||||
for (const index of indices) {
|
||||
const element = instance[index];
|
||||
|
||||
// Adopt the parser which was found at first.
|
||||
if (!config.parser && element.parser) {
|
||||
if (element.parser.error) {
|
||||
throw element.parser.error;
|
||||
}
|
||||
config.parser = element.parser;
|
||||
}
|
||||
|
||||
// Adopt the processor which was found at first.
|
||||
if (!config.processor && element.processor) {
|
||||
config.processor = element.processor;
|
||||
}
|
||||
|
||||
// Adopt the noInlineConfig which was found at first.
|
||||
if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {
|
||||
config.noInlineConfig = element.noInlineConfig;
|
||||
config.configNameOfNoInlineConfig = element.name;
|
||||
}
|
||||
|
||||
// Adopt the reportUnusedDisableDirectives which was found at first.
|
||||
if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {
|
||||
config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;
|
||||
}
|
||||
|
||||
// Collect ignorePatterns
|
||||
if (element.ignorePattern) {
|
||||
ignorePatterns.push(element.ignorePattern);
|
||||
}
|
||||
|
||||
// Merge others.
|
||||
mergeWithoutOverwrite(config.env, element.env);
|
||||
mergeWithoutOverwrite(config.globals, element.globals);
|
||||
mergeWithoutOverwrite(config.parserOptions, element.parserOptions);
|
||||
mergeWithoutOverwrite(config.settings, element.settings);
|
||||
mergePlugins(config.plugins, element.plugins);
|
||||
mergeRuleConfigs(config.rules, element.rules);
|
||||
}
|
||||
|
||||
// Create the predicate function for ignore patterns.
|
||||
if (ignorePatterns.length > 0) {
|
||||
config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect definitions.
|
||||
* @template T, U
|
||||
* @param {string} pluginId The plugin ID for prefix.
|
||||
* @param {Record<string,T>} defs The definitions to collect.
|
||||
* @param {Map<string, U>} map The map to output.
|
||||
* @param {function(T): U} [normalize] The normalize function for each value.
|
||||
* @returns {void}
|
||||
*/
|
||||
function collect(pluginId, defs, map, normalize) {
|
||||
if (defs) {
|
||||
const prefix = pluginId && `${pluginId}/`;
|
||||
|
||||
for (const [key, value] of Object.entries(defs)) {
|
||||
map.set(
|
||||
`${prefix}${key}`,
|
||||
normalize ? normalize(value) : value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a rule definition.
|
||||
* @param {Function|Rule} rule The rule definition to normalize.
|
||||
* @returns {Rule} The normalized rule definition.
|
||||
*/
|
||||
function normalizePluginRule(rule) {
|
||||
return typeof rule === "function" ? { create: rule } : rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the mutation methods from a given map.
|
||||
* @param {Map<any, any>} map The map object to delete.
|
||||
* @returns {void}
|
||||
*/
|
||||
function deleteMutationMethods(map) {
|
||||
Object.defineProperties(map, {
|
||||
clear: { configurable: true, value: void 0 },
|
||||
delete: { configurable: true, value: void 0 },
|
||||
set: { configurable: true, value: void 0 }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
|
||||
* @param {ConfigArrayElement[]} elements The config elements.
|
||||
* @param {ConfigArrayInternalSlots} slots The internal slots.
|
||||
* @returns {void}
|
||||
*/
|
||||
function initPluginMemberMaps(elements, slots) {
|
||||
const processed = new Set();
|
||||
|
||||
slots.envMap = new Map();
|
||||
slots.processorMap = new Map();
|
||||
slots.ruleMap = new Map();
|
||||
|
||||
for (const element of elements) {
|
||||
if (!element.plugins) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const [pluginId, value] of Object.entries(element.plugins)) {
|
||||
const plugin = value.definition;
|
||||
|
||||
if (!plugin || processed.has(pluginId)) {
|
||||
continue;
|
||||
}
|
||||
processed.add(pluginId);
|
||||
|
||||
collect(pluginId, plugin.environments, slots.envMap);
|
||||
collect(pluginId, plugin.processors, slots.processorMap);
|
||||
collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);
|
||||
}
|
||||
}
|
||||
|
||||
deleteMutationMethods(slots.envMap);
|
||||
deleteMutationMethods(slots.processorMap);
|
||||
deleteMutationMethods(slots.ruleMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
|
||||
* @param {ConfigArray} instance The config elements.
|
||||
* @returns {ConfigArrayInternalSlots} The extracted config.
|
||||
*/
|
||||
function ensurePluginMemberMaps(instance) {
|
||||
const slots = internalSlotsMap.get(instance);
|
||||
|
||||
if (!slots.ruleMap) {
|
||||
initPluginMemberMaps(instance, slots);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The Config Array.
|
||||
*
|
||||
* `ConfigArray` instance contains all settings, parsers, and plugins.
|
||||
* You need to call `ConfigArray#extractConfig(filePath)` method in order to
|
||||
* extract, merge and get only the config data which is related to an arbitrary
|
||||
* file.
|
||||
* @extends {Array<ConfigArrayElement>}
|
||||
*/
|
||||
class ConfigArray extends Array {
|
||||
|
||||
/**
|
||||
* Get the plugin environments.
|
||||
* The returned map cannot be mutated.
|
||||
* @type {ReadonlyMap<string, Environment>} The plugin environments.
|
||||
*/
|
||||
get pluginEnvironments() {
|
||||
return ensurePluginMemberMaps(this).envMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugin processors.
|
||||
* The returned map cannot be mutated.
|
||||
* @type {ReadonlyMap<string, Processor>} The plugin processors.
|
||||
*/
|
||||
get pluginProcessors() {
|
||||
return ensurePluginMemberMaps(this).processorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugin rules.
|
||||
* The returned map cannot be mutated.
|
||||
* @returns {ReadonlyMap<string, Rule>} The plugin rules.
|
||||
*/
|
||||
get pluginRules() {
|
||||
return ensurePluginMemberMaps(this).ruleMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this config has `root` flag.
|
||||
* @returns {boolean} `true` if this config array is root.
|
||||
*/
|
||||
isRoot() {
|
||||
for (let i = this.length - 1; i >= 0; --i) {
|
||||
const root = this[i].root;
|
||||
|
||||
if (typeof root === "boolean") {
|
||||
return root;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the config data which is related to a given file.
|
||||
* @param {string} filePath The absolute path to the target file.
|
||||
* @returns {ExtractedConfig} The extracted config data.
|
||||
*/
|
||||
extractConfig(filePath) {
|
||||
const { cache } = internalSlotsMap.get(this);
|
||||
const indices = getMatchedIndices(this, filePath);
|
||||
const cacheKey = indices.join(",");
|
||||
|
||||
if (!cache.has(cacheKey)) {
|
||||
cache.set(cacheKey, createConfig(this, indices));
|
||||
}
|
||||
|
||||
return cache.get(cacheKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given path is an additional lint target.
|
||||
* @param {string} filePath The absolute path to the target file.
|
||||
* @returns {boolean} `true` if the file is an additional lint target.
|
||||
*/
|
||||
isAdditionalTargetPath(filePath) {
|
||||
for (const { criteria, type } of this) {
|
||||
if (
|
||||
type === "config" &&
|
||||
criteria &&
|
||||
!criteria.endsWithWildcard &&
|
||||
criteria.test(filePath)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const exportObject = {
|
||||
ConfigArray,
|
||||
|
||||
/**
|
||||
* Get the used extracted configs.
|
||||
* CLIEngine will use this method to collect used deprecated rules.
|
||||
* @param {ConfigArray} instance The config array object to get.
|
||||
* @returns {ExtractedConfig[]} The used extracted configs.
|
||||
* @private
|
||||
*/
|
||||
getUsedExtractedConfigs(instance) {
|
||||
const { cache } = internalSlotsMap.get(instance);
|
||||
|
||||
return Array.from(cache.values());
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = exportObject;
|
||||
128
node_modules/eslint/lib/cli-engine/config-array/config-dependency.js
generated
vendored
128
node_modules/eslint/lib/cli-engine/config-array/config-dependency.js
generated
vendored
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* STOP!!! DO NOT MODIFY.
|
||||
*
|
||||
* This file is part of the ongoing work to move the eslintrc-style config
|
||||
* system into the @eslint/eslintrc package. This file needs to remain
|
||||
* unchanged in order for this work to proceed.
|
||||
*
|
||||
* If you think you need to change this file, please contact @nzakas first.
|
||||
*
|
||||
* Thanks in advance for your cooperation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview `ConfigDependency` class.
|
||||
*
|
||||
* `ConfigDependency` class expresses a loaded parser or plugin.
|
||||
*
|
||||
* If the parser or plugin was loaded successfully, it has `definition` property
|
||||
* and `filePath` property. Otherwise, it has `error` property.
|
||||
*
|
||||
* When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it
|
||||
* omits `definition` property.
|
||||
*
|
||||
* `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers
|
||||
* or plugins.
|
||||
*
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const util = require("util");
|
||||
|
||||
/**
|
||||
* The class is to store parsers or plugins.
|
||||
* This class hides the loaded object from `JSON.stringify()` and `console.log`.
|
||||
* @template T
|
||||
*/
|
||||
class ConfigDependency {
|
||||
|
||||
/**
|
||||
* Initialize this instance.
|
||||
* @param {Object} data The dependency data.
|
||||
* @param {T} [data.definition] The dependency if the loading succeeded.
|
||||
* @param {Error} [data.error] The error object if the loading failed.
|
||||
* @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.
|
||||
* @param {string} data.id The ID of this dependency.
|
||||
* @param {string} data.importerName The name of the config file which loads this dependency.
|
||||
* @param {string} data.importerPath The path to the config file which loads this dependency.
|
||||
*/
|
||||
constructor({
|
||||
definition = null,
|
||||
error = null,
|
||||
filePath = null,
|
||||
id,
|
||||
importerName,
|
||||
importerPath
|
||||
}) {
|
||||
|
||||
/**
|
||||
* The loaded dependency if the loading succeeded.
|
||||
* @type {T|null}
|
||||
*/
|
||||
this.definition = definition;
|
||||
|
||||
/**
|
||||
* The error object if the loading failed.
|
||||
* @type {Error|null}
|
||||
*/
|
||||
this.error = error;
|
||||
|
||||
/**
|
||||
* The loaded dependency if the loading succeeded.
|
||||
* @type {string|null}
|
||||
*/
|
||||
this.filePath = filePath;
|
||||
|
||||
/**
|
||||
* The ID of this dependency.
|
||||
* @type {string}
|
||||
*/
|
||||
this.id = id;
|
||||
|
||||
/**
|
||||
* The name of the config file which loads this dependency.
|
||||
* @type {string}
|
||||
*/
|
||||
this.importerName = importerName;
|
||||
|
||||
/**
|
||||
* The path to the config file which loads this dependency.
|
||||
* @type {string}
|
||||
*/
|
||||
this.importerPath = importerPath;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @returns {Object} a JSON compatible object.
|
||||
*/
|
||||
toJSON() {
|
||||
const obj = this[util.inspect.custom]();
|
||||
|
||||
// Display `error.message` (`Error#message` is unenumerable).
|
||||
if (obj.error instanceof Error) {
|
||||
obj.error = { ...obj.error, message: obj.error.message };
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @returns {Object} an object to display by `console.log()`.
|
||||
*/
|
||||
[util.inspect.custom]() {
|
||||
const {
|
||||
definition: _ignore, // eslint-disable-line no-unused-vars
|
||||
...obj
|
||||
} = this;
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/** @typedef {ConfigDependency<import("../../shared/types").Parser>} DependentParser */
|
||||
/** @typedef {ConfigDependency<import("../../shared/types").Plugin>} DependentPlugin */
|
||||
|
||||
module.exports = { ConfigDependency };
|
||||
158
node_modules/eslint/lib/cli-engine/config-array/extracted-config.js
generated
vendored
158
node_modules/eslint/lib/cli-engine/config-array/extracted-config.js
generated
vendored
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* STOP!!! DO NOT MODIFY.
|
||||
*
|
||||
* This file is part of the ongoing work to move the eslintrc-style config
|
||||
* system into the @eslint/eslintrc package. This file needs to remain
|
||||
* unchanged in order for this work to proceed.
|
||||
*
|
||||
* If you think you need to change this file, please contact @nzakas first.
|
||||
*
|
||||
* Thanks in advance for your cooperation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview `ExtractedConfig` class.
|
||||
*
|
||||
* `ExtractedConfig` class expresses a final configuration for a specific file.
|
||||
*
|
||||
* It provides one method.
|
||||
*
|
||||
* - `toCompatibleObjectAsConfigFileContent()`
|
||||
* Convert this configuration to the compatible object as the content of
|
||||
* config files. It converts the loaded parser and plugins to strings.
|
||||
* `CLIEngine#getConfigForFile(filePath)` method uses this method.
|
||||
*
|
||||
* `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.
|
||||
*
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const { IgnorePattern } = require("./ignore-pattern");
|
||||
|
||||
// For VSCode intellisense
|
||||
/** @typedef {import("../../shared/types").ConfigData} ConfigData */
|
||||
/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
|
||||
/** @typedef {import("../../shared/types").SeverityConf} SeverityConf */
|
||||
/** @typedef {import("./config-dependency").DependentParser} DependentParser */
|
||||
/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
|
||||
|
||||
/**
|
||||
* Check if `xs` starts with `ys`.
|
||||
* @template T
|
||||
* @param {T[]} xs The array to check.
|
||||
* @param {T[]} ys The array that may be the first part of `xs`.
|
||||
* @returns {boolean} `true` if `xs` starts with `ys`.
|
||||
*/
|
||||
function startsWith(xs, ys) {
|
||||
return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The class for extracted config data.
|
||||
*/
|
||||
class ExtractedConfig {
|
||||
constructor() {
|
||||
|
||||
/**
|
||||
* The config name what `noInlineConfig` setting came from.
|
||||
* @type {string}
|
||||
*/
|
||||
this.configNameOfNoInlineConfig = "";
|
||||
|
||||
/**
|
||||
* Environments.
|
||||
* @type {Record<string, boolean>}
|
||||
*/
|
||||
this.env = {};
|
||||
|
||||
/**
|
||||
* Global variables.
|
||||
* @type {Record<string, GlobalConf>}
|
||||
*/
|
||||
this.globals = {};
|
||||
|
||||
/**
|
||||
* The glob patterns that ignore to lint.
|
||||
* @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}
|
||||
*/
|
||||
this.ignores = void 0;
|
||||
|
||||
/**
|
||||
* The flag that disables directive comments.
|
||||
* @type {boolean|undefined}
|
||||
*/
|
||||
this.noInlineConfig = void 0;
|
||||
|
||||
/**
|
||||
* Parser definition.
|
||||
* @type {DependentParser|null}
|
||||
*/
|
||||
this.parser = null;
|
||||
|
||||
/**
|
||||
* Options for the parser.
|
||||
* @type {Object}
|
||||
*/
|
||||
this.parserOptions = {};
|
||||
|
||||
/**
|
||||
* Plugin definitions.
|
||||
* @type {Record<string, DependentPlugin>}
|
||||
*/
|
||||
this.plugins = {};
|
||||
|
||||
/**
|
||||
* Processor ID.
|
||||
* @type {string|null}
|
||||
*/
|
||||
this.processor = null;
|
||||
|
||||
/**
|
||||
* The flag that reports unused `eslint-disable` directive comments.
|
||||
* @type {boolean|undefined}
|
||||
*/
|
||||
this.reportUnusedDisableDirectives = void 0;
|
||||
|
||||
/**
|
||||
* Rule settings.
|
||||
* @type {Record<string, [SeverityConf, ...any[]]>}
|
||||
*/
|
||||
this.rules = {};
|
||||
|
||||
/**
|
||||
* Shared settings.
|
||||
* @type {Object}
|
||||
*/
|
||||
this.settings = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this config to the compatible object as a config file content.
|
||||
* @returns {ConfigData} The converted object.
|
||||
*/
|
||||
toCompatibleObjectAsConfigFileContent() {
|
||||
const {
|
||||
/* eslint-disable no-unused-vars */
|
||||
configNameOfNoInlineConfig: _ignore1,
|
||||
processor: _ignore2,
|
||||
/* eslint-enable no-unused-vars */
|
||||
ignores,
|
||||
...config
|
||||
} = this;
|
||||
|
||||
config.parser = config.parser && config.parser.filePath;
|
||||
config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();
|
||||
config.ignorePatterns = ignores ? ignores.patterns : [];
|
||||
|
||||
// Strip the default patterns from `ignorePatterns`.
|
||||
if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {
|
||||
config.ignorePatterns =
|
||||
config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { ExtractedConfig };
|
||||
249
node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js
generated
vendored
249
node_modules/eslint/lib/cli-engine/config-array/ignore-pattern.js
generated
vendored
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
* STOP!!! DO NOT MODIFY.
|
||||
*
|
||||
* This file is part of the ongoing work to move the eslintrc-style config
|
||||
* system into the @eslint/eslintrc package. This file needs to remain
|
||||
* unchanged in order for this work to proceed.
|
||||
*
|
||||
* If you think you need to change this file, please contact @nzakas first.
|
||||
*
|
||||
* Thanks in advance for your cooperation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview `IgnorePattern` class.
|
||||
*
|
||||
* `IgnorePattern` class has the set of glob patterns and the base path.
|
||||
*
|
||||
* It provides two static methods.
|
||||
*
|
||||
* - `IgnorePattern.createDefaultIgnore(cwd)`
|
||||
* Create the default predicate function.
|
||||
* - `IgnorePattern.createIgnore(ignorePatterns)`
|
||||
* Create the predicate function from multiple `IgnorePattern` objects.
|
||||
*
|
||||
* It provides two properties and a method.
|
||||
*
|
||||
* - `patterns`
|
||||
* The glob patterns that ignore to lint.
|
||||
* - `basePath`
|
||||
* The base path of the glob patterns. If absolute paths existed in the
|
||||
* glob patterns, those are handled as relative paths to the base path.
|
||||
* - `getPatternsRelativeTo(basePath)`
|
||||
* Get `patterns` as modified for a given base path. It modifies the
|
||||
* absolute paths in the patterns as prepending the difference of two base
|
||||
* paths.
|
||||
*
|
||||
* `ConfigArrayFactory` creates `IgnorePattern` objects when it processes
|
||||
* `ignorePatterns` properties.
|
||||
*
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const assert = require("assert");
|
||||
const path = require("path");
|
||||
const ignore = require("ignore");
|
||||
const debug = require("debug")("eslint:ignore-pattern");
|
||||
|
||||
/** @typedef {ReturnType<import("ignore").default>} Ignore */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get the path to the common ancestor directory of given paths.
|
||||
* @param {string[]} sourcePaths The paths to calculate the common ancestor.
|
||||
* @returns {string} The path to the common ancestor directory.
|
||||
*/
|
||||
function getCommonAncestorPath(sourcePaths) {
|
||||
let result = sourcePaths[0];
|
||||
|
||||
for (let i = 1; i < sourcePaths.length; ++i) {
|
||||
const a = result;
|
||||
const b = sourcePaths[i];
|
||||
|
||||
// Set the shorter one (it's the common ancestor if one includes the other).
|
||||
result = a.length < b.length ? a : b;
|
||||
|
||||
// Set the common ancestor.
|
||||
for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {
|
||||
if (a[j] !== b[j]) {
|
||||
result = a.slice(0, lastSepPos);
|
||||
break;
|
||||
}
|
||||
if (a[j] === path.sep) {
|
||||
lastSepPos = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let resolvedResult = result || path.sep;
|
||||
|
||||
// if Windows common ancestor is root of drive must have trailing slash to be absolute.
|
||||
if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
|
||||
resolvedResult += path.sep;
|
||||
}
|
||||
return resolvedResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make relative path.
|
||||
* @param {string} from The source path to get relative path.
|
||||
* @param {string} to The destination path to get relative path.
|
||||
* @returns {string} The relative path.
|
||||
*/
|
||||
function relative(from, to) {
|
||||
const relPath = path.relative(from, to);
|
||||
|
||||
if (path.sep === "/") {
|
||||
return relPath;
|
||||
}
|
||||
return relPath.split(path.sep).join("/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the trailing slash if existed.
|
||||
* @param {string} filePath The path to check.
|
||||
* @returns {string} The trailing slash if existed.
|
||||
*/
|
||||
function dirSuffix(filePath) {
|
||||
const isDir = (
|
||||
filePath.endsWith(path.sep) ||
|
||||
(process.platform === "win32" && filePath.endsWith("/"))
|
||||
);
|
||||
|
||||
return isDir ? "/" : "";
|
||||
}
|
||||
|
||||
const DefaultPatterns = Object.freeze(["/**/node_modules/*"]);
|
||||
const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class IgnorePattern {
|
||||
|
||||
/**
|
||||
* The default patterns.
|
||||
* @type {string[]}
|
||||
*/
|
||||
static get DefaultPatterns() {
|
||||
return DefaultPatterns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the default predicate function.
|
||||
* @param {string} cwd The current working directory.
|
||||
* @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}
|
||||
* The preficate function.
|
||||
* The first argument is an absolute path that is checked.
|
||||
* The second argument is the flag to not ignore dotfiles.
|
||||
* If the predicate function returned `true`, it means the path should be ignored.
|
||||
*/
|
||||
static createDefaultIgnore(cwd) {
|
||||
return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the predicate function from multiple `IgnorePattern` objects.
|
||||
* @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.
|
||||
* @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}
|
||||
* The preficate function.
|
||||
* The first argument is an absolute path that is checked.
|
||||
* The second argument is the flag to not ignore dotfiles.
|
||||
* If the predicate function returned `true`, it means the path should be ignored.
|
||||
*/
|
||||
static createIgnore(ignorePatterns) {
|
||||
debug("Create with: %o", ignorePatterns);
|
||||
|
||||
const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));
|
||||
const patterns = [].concat(
|
||||
...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))
|
||||
);
|
||||
const ig = ignore().add([...DotPatterns, ...patterns]);
|
||||
const dotIg = ignore().add(patterns);
|
||||
|
||||
debug(" processed: %o", { basePath, patterns });
|
||||
|
||||
return Object.assign(
|
||||
(filePath, dot = false) => {
|
||||
assert(path.isAbsolute(filePath), "'filePath' should be an absolute path.");
|
||||
const relPathRaw = relative(basePath, filePath);
|
||||
const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));
|
||||
const adoptedIg = dot ? dotIg : ig;
|
||||
const result = relPath !== "" && adoptedIg.ignores(relPath);
|
||||
|
||||
debug("Check", { filePath, dot, relativePath: relPath, result });
|
||||
return result;
|
||||
},
|
||||
{ basePath, patterns }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a new `IgnorePattern` instance.
|
||||
* @param {string[]} patterns The glob patterns that ignore to lint.
|
||||
* @param {string} basePath The base path of `patterns`.
|
||||
*/
|
||||
constructor(patterns, basePath) {
|
||||
assert(path.isAbsolute(basePath), "'basePath' should be an absolute path.");
|
||||
|
||||
/**
|
||||
* The glob patterns that ignore to lint.
|
||||
* @type {string[]}
|
||||
*/
|
||||
this.patterns = patterns;
|
||||
|
||||
/**
|
||||
* The base path of `patterns`.
|
||||
* @type {string}
|
||||
*/
|
||||
this.basePath = basePath;
|
||||
|
||||
/**
|
||||
* If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.
|
||||
*
|
||||
* It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.
|
||||
* It's `false` as-is for `ignorePatterns` property in config files.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.loose = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get `patterns` as modified for a given base path. It modifies the
|
||||
* absolute paths in the patterns as prepending the difference of two base
|
||||
* paths.
|
||||
* @param {string} newBasePath The base path.
|
||||
* @returns {string[]} Modifired patterns.
|
||||
*/
|
||||
getPatternsRelativeTo(newBasePath) {
|
||||
assert(path.isAbsolute(newBasePath), "'newBasePath' should be an absolute path.");
|
||||
const { basePath, loose, patterns } = this;
|
||||
|
||||
if (newBasePath === basePath) {
|
||||
return patterns;
|
||||
}
|
||||
const prefix = `/${relative(newBasePath, basePath)}`;
|
||||
|
||||
return patterns.map(pattern => {
|
||||
const negative = pattern.startsWith("!");
|
||||
const head = negative ? "!" : "";
|
||||
const body = negative ? pattern.slice(1) : pattern;
|
||||
|
||||
if (body.startsWith("/") || body.startsWith("../")) {
|
||||
return `${head}${prefix}${body}`;
|
||||
}
|
||||
return loose ? pattern : `${head}${prefix}/**/${body}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { IgnorePattern };
|
||||
32
node_modules/eslint/lib/cli-engine/config-array/index.js
generated
vendored
32
node_modules/eslint/lib/cli-engine/config-array/index.js
generated
vendored
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* STOP!!! DO NOT MODIFY.
|
||||
*
|
||||
* This file is part of the ongoing work to move the eslintrc-style config
|
||||
* system into the @eslint/eslintrc package. This file needs to remain
|
||||
* unchanged in order for this work to proceed.
|
||||
*
|
||||
* If you think you need to change this file, please contact @nzakas first.
|
||||
*
|
||||
* Thanks in advance for your cooperation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview `ConfigArray` class.
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const { ConfigArray, getUsedExtractedConfigs } = require("./config-array");
|
||||
const { ConfigDependency } = require("./config-dependency");
|
||||
const { ExtractedConfig } = require("./extracted-config");
|
||||
const { IgnorePattern } = require("./ignore-pattern");
|
||||
const { OverrideTester } = require("./override-tester");
|
||||
|
||||
module.exports = {
|
||||
ConfigArray,
|
||||
ConfigDependency,
|
||||
ExtractedConfig,
|
||||
IgnorePattern,
|
||||
OverrideTester,
|
||||
getUsedExtractedConfigs
|
||||
};
|
||||
235
node_modules/eslint/lib/cli-engine/config-array/override-tester.js
generated
vendored
235
node_modules/eslint/lib/cli-engine/config-array/override-tester.js
generated
vendored
|
|
@ -1,235 +0,0 @@
|
|||
/*
|
||||
* STOP!!! DO NOT MODIFY.
|
||||
*
|
||||
* This file is part of the ongoing work to move the eslintrc-style config
|
||||
* system into the @eslint/eslintrc package. This file needs to remain
|
||||
* unchanged in order for this work to proceed.
|
||||
*
|
||||
* If you think you need to change this file, please contact @nzakas first.
|
||||
*
|
||||
* Thanks in advance for your cooperation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview `OverrideTester` class.
|
||||
*
|
||||
* `OverrideTester` class handles `files` property and `excludedFiles` property
|
||||
* of `overrides` config.
|
||||
*
|
||||
* It provides one method.
|
||||
*
|
||||
* - `test(filePath)`
|
||||
* Test if a file path matches the pair of `files` property and
|
||||
* `excludedFiles` property. The `filePath` argument must be an absolute
|
||||
* path.
|
||||
*
|
||||
* `ConfigArrayFactory` creates `OverrideTester` objects when it processes
|
||||
* `overrides` properties.
|
||||
*
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const assert = require("assert");
|
||||
const path = require("path");
|
||||
const util = require("util");
|
||||
const { Minimatch } = require("minimatch");
|
||||
const minimatchOpts = { dot: true, matchBase: true };
|
||||
|
||||
/**
|
||||
* @typedef {Object} Pattern
|
||||
* @property {InstanceType<Minimatch>[] | null} includes The positive matchers.
|
||||
* @property {InstanceType<Minimatch>[] | null} excludes The negative matchers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Normalize a given pattern to an array.
|
||||
* @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.
|
||||
* @returns {string[]|null} Normalized patterns.
|
||||
* @private
|
||||
*/
|
||||
function normalizePatterns(patterns) {
|
||||
if (Array.isArray(patterns)) {
|
||||
return patterns.filter(Boolean);
|
||||
}
|
||||
if (typeof patterns === "string" && patterns) {
|
||||
return [patterns];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the matchers of given patterns.
|
||||
* @param {string[]} patterns The patterns.
|
||||
* @returns {InstanceType<Minimatch>[] | null} The matchers.
|
||||
*/
|
||||
function toMatcher(patterns) {
|
||||
if (patterns.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return patterns.map(pattern => {
|
||||
if (/^\.[/\\]/u.test(pattern)) {
|
||||
return new Minimatch(
|
||||
pattern.slice(2),
|
||||
|
||||
// `./*.js` should not match with `subdir/foo.js`
|
||||
{ ...minimatchOpts, matchBase: false }
|
||||
);
|
||||
}
|
||||
return new Minimatch(pattern, minimatchOpts);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a given matcher to string.
|
||||
* @param {Pattern} matchers The matchers.
|
||||
* @returns {string} The string expression of the matcher.
|
||||
*/
|
||||
function patternToJson({ includes, excludes }) {
|
||||
return {
|
||||
includes: includes && includes.map(m => m.pattern),
|
||||
excludes: excludes && excludes.map(m => m.pattern)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The class to test given paths are matched by the patterns.
|
||||
*/
|
||||
class OverrideTester {
|
||||
|
||||
/**
|
||||
* Create a tester with given criteria.
|
||||
* If there are no criteria, returns `null`.
|
||||
* @param {string|string[]} files The glob patterns for included files.
|
||||
* @param {string|string[]} excludedFiles The glob patterns for excluded files.
|
||||
* @param {string} basePath The path to the base directory to test paths.
|
||||
* @returns {OverrideTester|null} The created instance or `null`.
|
||||
*/
|
||||
static create(files, excludedFiles, basePath) {
|
||||
const includePatterns = normalizePatterns(files);
|
||||
const excludePatterns = normalizePatterns(excludedFiles);
|
||||
let endsWithWildcard = false;
|
||||
|
||||
if (includePatterns.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Rejects absolute paths or relative paths to parents.
|
||||
for (const pattern of includePatterns) {
|
||||
if (path.isAbsolute(pattern) || pattern.includes("..")) {
|
||||
throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
|
||||
}
|
||||
if (pattern.endsWith("*")) {
|
||||
endsWithWildcard = true;
|
||||
}
|
||||
}
|
||||
for (const pattern of excludePatterns) {
|
||||
if (path.isAbsolute(pattern) || pattern.includes("..")) {
|
||||
throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
|
||||
}
|
||||
}
|
||||
|
||||
const includes = toMatcher(includePatterns);
|
||||
const excludes = toMatcher(excludePatterns);
|
||||
|
||||
return new OverrideTester(
|
||||
[{ includes, excludes }],
|
||||
basePath,
|
||||
endsWithWildcard
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine two testers by logical and.
|
||||
* If either of the testers was `null`, returns the other tester.
|
||||
* The `basePath` property of the two must be the same value.
|
||||
* @param {OverrideTester|null} a A tester.
|
||||
* @param {OverrideTester|null} b Another tester.
|
||||
* @returns {OverrideTester|null} Combined tester.
|
||||
*/
|
||||
static and(a, b) {
|
||||
if (!b) {
|
||||
return a && new OverrideTester(
|
||||
a.patterns,
|
||||
a.basePath,
|
||||
a.endsWithWildcard
|
||||
);
|
||||
}
|
||||
if (!a) {
|
||||
return new OverrideTester(
|
||||
b.patterns,
|
||||
b.basePath,
|
||||
b.endsWithWildcard
|
||||
);
|
||||
}
|
||||
|
||||
assert.strictEqual(a.basePath, b.basePath);
|
||||
return new OverrideTester(
|
||||
a.patterns.concat(b.patterns),
|
||||
a.basePath,
|
||||
a.endsWithWildcard || b.endsWithWildcard
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this instance.
|
||||
* @param {Pattern[]} patterns The matchers.
|
||||
* @param {string} basePath The base path.
|
||||
* @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.
|
||||
*/
|
||||
constructor(patterns, basePath, endsWithWildcard = false) {
|
||||
|
||||
/** @type {Pattern[]} */
|
||||
this.patterns = patterns;
|
||||
|
||||
/** @type {string} */
|
||||
this.basePath = basePath;
|
||||
|
||||
/** @type {boolean} */
|
||||
this.endsWithWildcard = endsWithWildcard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a given path is matched or not.
|
||||
* @param {string} filePath The absolute path to the target file.
|
||||
* @returns {boolean} `true` if the path was matched.
|
||||
*/
|
||||
test(filePath) {
|
||||
if (typeof filePath !== "string" || !path.isAbsolute(filePath)) {
|
||||
throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);
|
||||
}
|
||||
const relativePath = path.relative(this.basePath, filePath);
|
||||
|
||||
return this.patterns.every(({ includes, excludes }) => (
|
||||
(!includes || includes.some(m => m.match(relativePath))) &&
|
||||
(!excludes || !excludes.some(m => m.match(relativePath)))
|
||||
));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @returns {Object} a JSON compatible object.
|
||||
*/
|
||||
toJSON() {
|
||||
if (this.patterns.length === 1) {
|
||||
return {
|
||||
...patternToJson(this.patterns[0]),
|
||||
basePath: this.basePath
|
||||
};
|
||||
}
|
||||
return {
|
||||
AND: this.patterns.map(patternToJson),
|
||||
basePath: this.basePath
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @returns {Object} an object to display by `console.log()`.
|
||||
*/
|
||||
[util.inspect.custom]() {
|
||||
return this.toJSON();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { OverrideTester };
|
||||
26
node_modules/eslint/lib/cli-engine/file-enumerator.js
generated
vendored
26
node_modules/eslint/lib/cli-engine/file-enumerator.js
generated
vendored
|
|
@ -38,10 +38,15 @@ const fs = require("fs");
|
|||
const path = require("path");
|
||||
const getGlobParent = require("glob-parent");
|
||||
const isGlob = require("is-glob");
|
||||
const { escapeRegExp } = require("lodash");
|
||||
const escapeRegExp = require("escape-string-regexp");
|
||||
const { Minimatch } = require("minimatch");
|
||||
const { IgnorePattern } = require("./config-array");
|
||||
const { CascadingConfigArrayFactory } = require("./cascading-config-array-factory");
|
||||
|
||||
const {
|
||||
Legacy: {
|
||||
IgnorePattern,
|
||||
CascadingConfigArrayFactory
|
||||
}
|
||||
} = require("@eslint/eslintrc");
|
||||
const debug = require("debug")("eslint:file-enumerator");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -208,7 +213,11 @@ class FileEnumerator {
|
|||
*/
|
||||
constructor({
|
||||
cwd = process.cwd(),
|
||||
configArrayFactory = new CascadingConfigArrayFactory({ cwd }),
|
||||
configArrayFactory = new CascadingConfigArrayFactory({
|
||||
cwd,
|
||||
eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
|
||||
eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
|
||||
}),
|
||||
extensions = null,
|
||||
globInputPaths = true,
|
||||
errorOnUnmatchedPattern = true,
|
||||
|
|
@ -424,9 +433,14 @@ class FileEnumerator {
|
|||
// Enumerate the files of this directory.
|
||||
for (const entry of readdirSafeSync(directoryPath)) {
|
||||
const filePath = path.join(directoryPath, entry.name);
|
||||
const fileInfo = entry.isSymbolicLink() ? statSafeSync(filePath) : entry;
|
||||
|
||||
if (!fileInfo) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the file is matched.
|
||||
if (entry.isFile()) {
|
||||
if (fileInfo.isFile()) {
|
||||
if (!config) {
|
||||
config = configArrayFactory.getConfigArrayForFile(
|
||||
filePath,
|
||||
|
|
@ -462,7 +476,7 @@ class FileEnumerator {
|
|||
}
|
||||
|
||||
// Dive into the sub directory.
|
||||
} else if (options.recursive && entry.isDirectory()) {
|
||||
} else if (options.recursive && fileInfo.isDirectory()) {
|
||||
if (!config) {
|
||||
config = configArrayFactory.getConfigArrayForFile(
|
||||
filePath,
|
||||
|
|
|
|||
8
node_modules/eslint/lib/cli-engine/formatters/html-template-message.html
generated
vendored
8
node_modules/eslint/lib/cli-engine/formatters/html-template-message.html
generated
vendored
|
|
@ -1,8 +0,0 @@
|
|||
<tr style="display:none" class="f-<%= parentIndex %>">
|
||||
<td><%= lineNumber %>:<%= columnNumber %></td>
|
||||
<td class="clr-<%= severityNumber %>"><%= severityName %></td>
|
||||
<td><%- message %></td>
|
||||
<td>
|
||||
<a href="<%= ruleUrl %>" target="_blank" rel="noopener noreferrer"><%= ruleId %></a>
|
||||
</td>
|
||||
</tr>
|
||||
115
node_modules/eslint/lib/cli-engine/formatters/html-template-page.html
generated
vendored
115
node_modules/eslint/lib/cli-engine/formatters/html-template-page.html
generated
vendored
|
|
@ -1,115 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ESLint Report</title>
|
||||
<style>
|
||||
body {
|
||||
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;
|
||||
}
|
||||
th {
|
||||
font-weight:400;
|
||||
font-size:medium;
|
||||
text-align:left;
|
||||
cursor:pointer
|
||||
}
|
||||
td.clr-1, td.clr-2, th span {
|
||||
font-weight:700
|
||||
}
|
||||
th span {
|
||||
float:right;
|
||||
margin-left:20px
|
||||
}
|
||||
th span:after {
|
||||
content:"";
|
||||
clear:both;
|
||||
display:block
|
||||
}
|
||||
tr:last-child td {
|
||||
border-bottom:none
|
||||
}
|
||||
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-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
|
||||
}
|
||||
td {
|
||||
border-bottom:1px solid #ddd
|
||||
}
|
||||
td.clr-1 {
|
||||
color:#f0ad4e
|
||||
}
|
||||
td.clr-2 {
|
||||
color:#b94a48
|
||||
}
|
||||
td a {
|
||||
color:#3a33d1;
|
||||
text-decoration:none
|
||||
}
|
||||
td a:hover {
|
||||
color:#272296;
|
||||
text-decoration:underline
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="overview" class="bg-<%= reportColor %>">
|
||||
<h1>ESLint Report</h1>
|
||||
<div>
|
||||
<span><%= reportSummary %></span> - Generated on <%= date %>
|
||||
</div>
|
||||
</div>
|
||||
<table>
|
||||
<tbody>
|
||||
<%= results %>
|
||||
</tbody>
|
||||
</table>
|
||||
<script type="text/javascript">
|
||||
var groups = document.querySelectorAll("tr[data-group]");
|
||||
for (i = 0; i < groups.length; i++) {
|
||||
groups[i].addEventListener("click", function() {
|
||||
var inGroup = document.getElementsByClassName(this.getAttribute("data-group"));
|
||||
this.innerHTML = (this.innerHTML.indexOf("+") > -1) ? this.innerHTML.replace("+", "-") : this.innerHTML.replace("-", "+");
|
||||
for (var j = 0; j < inGroup.length; j++) {
|
||||
inGroup[j].style.display = (inGroup[j].style.display !== "none") ? "none" : "table-row";
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
6
node_modules/eslint/lib/cli-engine/formatters/html-template-result.html
generated
vendored
6
node_modules/eslint/lib/cli-engine/formatters/html-template-result.html
generated
vendored
|
|
@ -1,6 +0,0 @@
|
|||
<tr class="bg-<%- color %>" data-group="f-<%- index %>">
|
||||
<th colspan="4">
|
||||
[+] <%- filePath %>
|
||||
<span><%- summary %></span>
|
||||
</th>
|
||||
</tr>
|
||||
206
node_modules/eslint/lib/cli-engine/formatters/html.js
generated
vendored
206
node_modules/eslint/lib/cli-engine/formatters/html.js
generated
vendored
|
|
@ -4,17 +4,153 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const lodash = require("lodash");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const pageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-page.html"), "utf-8"));
|
||||
const messageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-message.html"), "utf-8"));
|
||||
const resultTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-result.html"), "utf-8"));
|
||||
const encodeHTML = (function() {
|
||||
const encodeHTMLRules = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
'"': """,
|
||||
"'": "'"
|
||||
};
|
||||
const matchHTML = /[&<>"']/ug;
|
||||
|
||||
return function(code) {
|
||||
return code
|
||||
? code.toString().replace(matchHTML, m => encodeHTMLRules[m] || m)
|
||||
: "";
|
||||
};
|
||||
}());
|
||||
|
||||
/**
|
||||
* Get the final HTML document.
|
||||
* @param {Object} it data for the document.
|
||||
* @returns {string} HTML document.
|
||||
*/
|
||||
function pageTemplate(it) {
|
||||
const { reportColor, reportSummary, date, results } = it;
|
||||
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ESLint Report</title>
|
||||
<style>
|
||||
body {
|
||||
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;
|
||||
}
|
||||
th {
|
||||
font-weight:400;
|
||||
font-size:medium;
|
||||
text-align:left;
|
||||
cursor:pointer
|
||||
}
|
||||
td.clr-1, td.clr-2, th span {
|
||||
font-weight:700
|
||||
}
|
||||
th span {
|
||||
float:right;
|
||||
margin-left:20px
|
||||
}
|
||||
th span:after {
|
||||
content:"";
|
||||
clear:both;
|
||||
display:block
|
||||
}
|
||||
tr:last-child td {
|
||||
border-bottom:none
|
||||
}
|
||||
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-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
|
||||
}
|
||||
td {
|
||||
border-bottom:1px solid #ddd
|
||||
}
|
||||
td.clr-1 {
|
||||
color:#f0ad4e
|
||||
}
|
||||
td.clr-2 {
|
||||
color:#b94a48
|
||||
}
|
||||
td a {
|
||||
color:#3a33d1;
|
||||
text-decoration:none
|
||||
}
|
||||
td a:hover {
|
||||
color:#272296;
|
||||
text-decoration:underline
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="overview" class="bg-${reportColor}">
|
||||
<h1>ESLint Report</h1>
|
||||
<div>
|
||||
<span>${reportSummary}</span> - Generated on ${date}
|
||||
</div>
|
||||
</div>
|
||||
<table>
|
||||
<tbody>
|
||||
${results}
|
||||
</tbody>
|
||||
</table>
|
||||
<script type="text/javascript">
|
||||
var groups = document.querySelectorAll("tr[data-group]");
|
||||
for (i = 0; i < groups.length; i++) {
|
||||
groups[i].addEventListener("click", function() {
|
||||
var inGroup = document.getElementsByClassName(this.getAttribute("data-group"));
|
||||
this.innerHTML = (this.innerHTML.indexOf("+") > -1) ? this.innerHTML.replace("+", "-") : this.innerHTML.replace("-", "+");
|
||||
for (var j = 0; j < inGroup.length; j++) {
|
||||
inGroup[j].style.display = (inGroup[j].style.display !== "none") ? "none" : "table-row";
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`.trimLeft();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a word and a count, append an s if count is not one.
|
||||
|
|
@ -58,6 +194,35 @@ function renderColor(totalErrors, totalWarnings) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HTML (table row) describing a single message.
|
||||
* @param {Object} it data for the message.
|
||||
* @returns {string} HTML (table row) describing the message.
|
||||
*/
|
||||
function messageTemplate(it) {
|
||||
const {
|
||||
parentIndex,
|
||||
lineNumber,
|
||||
columnNumber,
|
||||
severityNumber,
|
||||
severityName,
|
||||
message,
|
||||
ruleUrl,
|
||||
ruleId
|
||||
} = it;
|
||||
|
||||
return `
|
||||
<tr style="display:none" class="f-${parentIndex}">
|
||||
<td>${lineNumber}:${columnNumber}</td>
|
||||
<td class="clr-${severityNumber}">${severityName}</td>
|
||||
<td>${encodeHTML(message)}</td>
|
||||
<td>
|
||||
<a href="${ruleUrl ? ruleUrl : ""}" target="_blank" rel="noopener noreferrer">${ruleId ? ruleId : ""}</a>
|
||||
</td>
|
||||
</tr>
|
||||
`.trimLeft();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HTML (table rows) describing the messages.
|
||||
* @param {Array} messages Messages.
|
||||
|
|
@ -72,7 +237,7 @@ function renderMessages(messages, parentIndex, rulesMeta) {
|
|||
* @param {Object} message Message.
|
||||
* @returns {string} HTML (table row) describing a message.
|
||||
*/
|
||||
return lodash.map(messages, message => {
|
||||
return messages.map(message => {
|
||||
const lineNumber = message.line || 0;
|
||||
const columnNumber = message.column || 0;
|
||||
let ruleUrl;
|
||||
|
|
@ -80,7 +245,9 @@ function renderMessages(messages, parentIndex, rulesMeta) {
|
|||
if (rulesMeta) {
|
||||
const meta = rulesMeta[message.ruleId];
|
||||
|
||||
ruleUrl = lodash.get(meta, "docs.url", null);
|
||||
if (meta && meta.docs && meta.docs.url) {
|
||||
ruleUrl = meta.docs.url;
|
||||
}
|
||||
}
|
||||
|
||||
return messageTemplate({
|
||||
|
|
@ -96,6 +263,24 @@ function renderMessages(messages, parentIndex, rulesMeta) {
|
|||
}).join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HTML (table row) describing the result for a single file.
|
||||
* @param {Object} it data for the file.
|
||||
* @returns {string} HTML (table row) describing the result for the file.
|
||||
*/
|
||||
function resultTemplate(it) {
|
||||
const { color, index, filePath, summary } = it;
|
||||
|
||||
return `
|
||||
<tr class="bg-${color}" data-group="f-${index}">
|
||||
<th colspan="4">
|
||||
[+] ${encodeHTML(filePath)}
|
||||
<span>${encodeHTML(summary)}</span>
|
||||
</th>
|
||||
</tr>
|
||||
`.trimLeft();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
* @param {Array} results Test results.
|
||||
|
|
@ -103,12 +288,11 @@ function renderMessages(messages, parentIndex, rulesMeta) {
|
|||
* @returns {string} HTML string describing the results.
|
||||
*/
|
||||
function renderResults(results, rulesMeta) {
|
||||
return lodash.map(results, (result, index) => resultTemplate({
|
||||
return results.map((result, index) => resultTemplate({
|
||||
index,
|
||||
color: renderColor(result.errorCount, result.warningCount),
|
||||
filePath: result.filePath,
|
||||
summary: renderSummary(result.errorCount, result.warningCount)
|
||||
|
||||
}) + renderMessages(result.messages, index, rulesMeta)).join("\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
63
node_modules/eslint/lib/cli-engine/lint-result-cache.js
generated
vendored
63
node_modules/eslint/lib/cli-engine/lint-result-cache.js
generated
vendored
|
|
@ -15,6 +15,8 @@ const stringify = require("json-stable-stringify-without-jsonify");
|
|||
const pkg = require("../../package.json");
|
||||
const hash = require("./hash");
|
||||
|
||||
const debug = require("debug")("eslint:lint-result-cache");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -22,6 +24,22 @@ const hash = require("./hash");
|
|||
const configHashCache = new WeakMap();
|
||||
const nodeVersion = process && process.version;
|
||||
|
||||
const validCacheStrategies = ["metadata", "content"];
|
||||
const invalidCacheStrategyErrorMessage = `Cache strategy must be one of: ${validCacheStrategies
|
||||
.map(strategy => `"${strategy}"`)
|
||||
.join(", ")}`;
|
||||
|
||||
/**
|
||||
* Tests whether a provided cacheStrategy is valid
|
||||
* @param {string} cacheStrategy The cache strategy to use
|
||||
* @returns {boolean} true if `cacheStrategy` is one of `validCacheStrategies`; false otherwise
|
||||
*/
|
||||
function isValidCacheStrategy(cacheStrategy) {
|
||||
return (
|
||||
validCacheStrategies.indexOf(cacheStrategy) !== -1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the hash of the config
|
||||
* @param {ConfigArray} config The config.
|
||||
|
|
@ -49,12 +67,30 @@ class LintResultCache {
|
|||
/**
|
||||
* Creates a new LintResultCache instance.
|
||||
* @param {string} cacheFileLocation The cache file location.
|
||||
* configuration lookup by file path).
|
||||
* @param {"metadata" | "content"} cacheStrategy The cache strategy to use.
|
||||
*/
|
||||
constructor(cacheFileLocation) {
|
||||
constructor(cacheFileLocation, cacheStrategy) {
|
||||
assert(cacheFileLocation, "Cache file location is required");
|
||||
assert(cacheStrategy, "Cache strategy is required");
|
||||
assert(
|
||||
isValidCacheStrategy(cacheStrategy),
|
||||
invalidCacheStrategyErrorMessage
|
||||
);
|
||||
|
||||
this.fileEntryCache = fileEntryCache.create(cacheFileLocation);
|
||||
debug(`Caching results to ${cacheFileLocation}`);
|
||||
|
||||
const useChecksum = cacheStrategy === "content";
|
||||
|
||||
debug(
|
||||
`Using "${cacheStrategy}" strategy to detect changes`
|
||||
);
|
||||
|
||||
this.fileEntryCache = fileEntryCache.create(
|
||||
cacheFileLocation,
|
||||
void 0,
|
||||
useChecksum
|
||||
);
|
||||
this.cacheFileLocation = cacheFileLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,17 +112,28 @@ class LintResultCache {
|
|||
* was previously linted
|
||||
* If any of these are not true, we will not reuse the lint results.
|
||||
*/
|
||||
|
||||
const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath);
|
||||
const hashOfConfig = hashOfConfigFor(config);
|
||||
const changed = fileDescriptor.changed || fileDescriptor.meta.hashOfConfig !== hashOfConfig;
|
||||
const changed =
|
||||
fileDescriptor.changed ||
|
||||
fileDescriptor.meta.hashOfConfig !== hashOfConfig;
|
||||
|
||||
if (fileDescriptor.notFound || changed) {
|
||||
if (fileDescriptor.notFound) {
|
||||
debug(`File not found on the file system: ${filePath}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
debug(`Cache entry not found or no longer valid: ${filePath}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// If source is present but null, need to reread the file from the filesystem.
|
||||
if (fileDescriptor.meta.results && fileDescriptor.meta.results.source === null) {
|
||||
if (
|
||||
fileDescriptor.meta.results &&
|
||||
fileDescriptor.meta.results.source === null
|
||||
) {
|
||||
debug(`Rereading cached result source from filesystem: ${filePath}`);
|
||||
fileDescriptor.meta.results.source = fs.readFileSync(filePath, "utf-8");
|
||||
}
|
||||
|
||||
|
|
@ -112,6 +159,7 @@ class LintResultCache {
|
|||
const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath);
|
||||
|
||||
if (fileDescriptor && !fileDescriptor.notFound) {
|
||||
debug(`Updating cached result: ${filePath}`);
|
||||
|
||||
// Serialize the result, except that we want to remove the file source if present.
|
||||
const resultToSerialize = Object.assign({}, result);
|
||||
|
|
@ -135,6 +183,7 @@ class LintResultCache {
|
|||
* @returns {void}
|
||||
*/
|
||||
reconcile() {
|
||||
debug(`Persisting cached results: ${this.cacheFileLocation}`);
|
||||
this.fileEntryCache.reconcile();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
15
node_modules/eslint/lib/cli.js
generated
vendored
15
node_modules/eslint/lib/cli.js
generated
vendored
|
|
@ -32,6 +32,7 @@ const debug = require("debug")("eslint:cli");
|
|||
/** @typedef {import("./eslint/eslint").ESLintOptions} ESLintOptions */
|
||||
/** @typedef {import("./eslint/eslint").LintMessage} LintMessage */
|
||||
/** @typedef {import("./eslint/eslint").LintResult} LintResult */
|
||||
/** @typedef {import("./options").ParsedCLIOptions} ParsedCLIOptions */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
|
@ -54,7 +55,7 @@ function quietFixPredicate(message) {
|
|||
|
||||
/**
|
||||
* Translates the CLI options into the options expected by the CLIEngine.
|
||||
* @param {Object} cliOptions The CLI options to translate.
|
||||
* @param {ParsedCLIOptions} cliOptions The CLI options to translate.
|
||||
* @returns {ESLintOptions} The options object for the CLIEngine.
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -62,6 +63,7 @@ function translateOptions({
|
|||
cache,
|
||||
cacheFile,
|
||||
cacheLocation,
|
||||
cacheStrategy,
|
||||
config,
|
||||
env,
|
||||
errorOnUnmatchedPattern,
|
||||
|
|
@ -88,6 +90,7 @@ function translateOptions({
|
|||
allowInlineConfig: inlineConfig,
|
||||
cache,
|
||||
cacheLocation: cacheLocation || cacheFile,
|
||||
cacheStrategy,
|
||||
errorOnUnmatchedPattern,
|
||||
extensions: ext,
|
||||
fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
|
||||
|
|
@ -219,6 +222,8 @@ const cli = {
|
|||
if (Array.isArray(args)) {
|
||||
debug("CLI args: %o", args.slice(2));
|
||||
}
|
||||
|
||||
/** @type {ParsedCLIOptions} */
|
||||
let options;
|
||||
|
||||
try {
|
||||
|
|
@ -299,12 +304,16 @@ const cli = {
|
|||
await ESLint.outputFixes(results);
|
||||
}
|
||||
|
||||
let resultsToPrint = results;
|
||||
|
||||
if (options.quiet) {
|
||||
debug("Quiet mode enabled - filtering out warnings");
|
||||
results = ESLint.getErrorResults(results);
|
||||
resultsToPrint = ESLint.getErrorResults(resultsToPrint);
|
||||
}
|
||||
|
||||
if (await printResults(engine, results, options.format, options.outputFile)) {
|
||||
if (await printResults(engine, resultsToPrint, options.format, options.outputFile)) {
|
||||
|
||||
// Errors and warnings from the original unfiltered results should determine the exit code
|
||||
const { errorCount, warningCount } = countErrors(results);
|
||||
const tooManyWarnings =
|
||||
options.maxWarnings >= 0 && warningCount > options.maxWarnings;
|
||||
|
|
|
|||
52
node_modules/eslint/lib/config/default-config.js
generated
vendored
Normal file
52
node_modules/eslint/lib/config/default-config.js
generated
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* @fileoverview Default configuration
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const Rules = require("../rules");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
exports.defaultConfig = [
|
||||
{
|
||||
plugins: {
|
||||
"@": {
|
||||
parsers: {
|
||||
espree: require("espree")
|
||||
},
|
||||
|
||||
/*
|
||||
* Because we try to delay loading rules until absolutely
|
||||
* 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.
|
||||
*/
|
||||
rules: new Proxy({}, {
|
||||
get(target, property) {
|
||||
return Rules.get(property);
|
||||
},
|
||||
|
||||
has(target, property) {
|
||||
return Rules.has(property);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
ignores: [
|
||||
"**/node_modules/**",
|
||||
".git/**"
|
||||
],
|
||||
languageOptions: {
|
||||
parser: "@/espree"
|
||||
}
|
||||
}
|
||||
];
|
||||
125
node_modules/eslint/lib/config/flat-config-array.js
generated
vendored
Normal file
125
node_modules/eslint/lib/config/flat-config-array.js
generated
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* @fileoverview Flat Config Array
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const { ConfigArray, ConfigArraySymbol } = require("@humanwhocodes/config-array");
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const ruleValidator = new RuleValidator();
|
||||
|
||||
/**
|
||||
* Splits a plugin identifier in the form a/b/c into two parts: a/b and c.
|
||||
* @param {string} identifier The identifier to parse.
|
||||
* @returns {{objectName: string, pluginName: string}} The parts of the plugin
|
||||
* name.
|
||||
*/
|
||||
function splitPluginIdentifier(identifier) {
|
||||
const parts = identifier.split("/");
|
||||
|
||||
return {
|
||||
objectName: parts.pop(),
|
||||
pluginName: parts.join("/")
|
||||
};
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Represents an array containing configuration information for ESLint.
|
||||
*/
|
||||
class FlatConfigArray extends ConfigArray {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {*[]} configs An array of configuration information.
|
||||
* @param {{basePath: string, baseConfig: FlatConfig}} options The options
|
||||
* to use for the config array instance.
|
||||
*/
|
||||
constructor(configs, { basePath, baseConfig = defaultConfig }) {
|
||||
super(configs, {
|
||||
basePath,
|
||||
schema: flatConfigSchema
|
||||
});
|
||||
|
||||
this.unshift(baseConfig);
|
||||
}
|
||||
|
||||
/* eslint-disable class-methods-use-this */
|
||||
/**
|
||||
* Replaces a config with another config to allow us to put strings
|
||||
* in the config array that will be replaced by objects before
|
||||
* normalization.
|
||||
* @param {Object} config The config to preprocess.
|
||||
* @returns {Object} The preprocessed config.
|
||||
*/
|
||||
[ConfigArraySymbol.preprocessConfig](config) {
|
||||
if (config === "eslint:recommended") {
|
||||
return recommendedConfig;
|
||||
}
|
||||
|
||||
if (config === "eslint:all") {
|
||||
return allConfig;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the config by replacing plugin references with their objects
|
||||
* and validating rule option schemas.
|
||||
* @param {Object} config The config to finalize.
|
||||
* @returns {Object} The finalized config.
|
||||
* @throws {TypeError} If the config is invalid.
|
||||
*/
|
||||
[ConfigArraySymbol.finalizeConfig](config) {
|
||||
|
||||
const { plugins, languageOptions, processor } = config;
|
||||
|
||||
// Check parser value
|
||||
if (languageOptions && languageOptions.parser && typeof languageOptions.parser === "string") {
|
||||
const { pluginName, objectName: parserName } = 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}".`);
|
||||
}
|
||||
|
||||
languageOptions.parser = plugins[pluginName].parsers[parserName];
|
||||
}
|
||||
|
||||
// Check processor value
|
||||
if (processor && typeof processor === "string") {
|
||||
const { pluginName, objectName: processorName } = 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}".`);
|
||||
}
|
||||
|
||||
config.processor = plugins[pluginName].processors[processorName];
|
||||
}
|
||||
|
||||
ruleValidator.validate(config);
|
||||
|
||||
return config;
|
||||
}
|
||||
/* eslint-enable class-methods-use-this */
|
||||
|
||||
}
|
||||
|
||||
exports.FlatConfigArray = FlatConfigArray;
|
||||
452
node_modules/eslint/lib/config/flat-config-schema.js
generated
vendored
Normal file
452
node_modules/eslint/lib/config/flat-config-schema.js
generated
vendored
Normal file
|
|
@ -0,0 +1,452 @@
|
|||
/**
|
||||
* @fileoverview Flat config schema
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @typedef ObjectPropertySchema
|
||||
* @property {Function|string} merge The function or name of the function to call
|
||||
* to merge multiple objects with this property.
|
||||
* @property {Function|string} validate The function or name of the function to call
|
||||
* to validate the value of this property.
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const ruleSeverities = new Map([
|
||||
[0, 0], ["off", 0],
|
||||
[1, 1], ["warn", 1],
|
||||
[2, 2], ["error", 2]
|
||||
]);
|
||||
|
||||
const globalVariablesValues = new Set([
|
||||
true, "true", "writable", "writeable",
|
||||
false, "false", "readonly", "readable", null,
|
||||
"off"
|
||||
]);
|
||||
|
||||
/**
|
||||
* Check if a value is a non-null object.
|
||||
* @param {any} value The value to check.
|
||||
* @returns {boolean} `true` if the value is a non-null object.
|
||||
*/
|
||||
function isNonNullObject(value) {
|
||||
return typeof value === "object" && value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a value is undefined.
|
||||
* @param {any} value The value to check.
|
||||
* @returns {boolean} `true` if the value is undefined.
|
||||
*/
|
||||
function isUndefined(value) {
|
||||
return typeof value === "undefined";
|
||||
}
|
||||
|
||||
/**
|
||||
* Deeply merges two objects.
|
||||
* @param {Object} first The base object.
|
||||
* @param {Object} second The overrides object.
|
||||
* @returns {Object} An object with properties from both first and second.
|
||||
*/
|
||||
function deepMerge(first = {}, second = {}) {
|
||||
|
||||
/*
|
||||
* If the second value is an array, just return it. We don't merge
|
||||
* arrays because order matters and we can't know the correct order.
|
||||
*/
|
||||
if (Array.isArray(second)) {
|
||||
return second;
|
||||
}
|
||||
|
||||
/*
|
||||
* First create a result object where properties from the second object
|
||||
* overwrite properties from the first. This sets up a baseline to use
|
||||
* later rather than needing to inspect and change every property
|
||||
* individually.
|
||||
*/
|
||||
const result = {
|
||||
...first,
|
||||
...second
|
||||
};
|
||||
|
||||
for (const key of Object.keys(second)) {
|
||||
|
||||
// avoid hairy edge case
|
||||
if (key === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const firstValue = first[key];
|
||||
const secondValue = second[key];
|
||||
|
||||
if (isNonNullObject(firstValue)) {
|
||||
result[key] = deepMerge(firstValue, secondValue);
|
||||
} else if (isUndefined(firstValue)) {
|
||||
if (isNonNullObject(secondValue)) {
|
||||
result[key] = deepMerge(
|
||||
Array.isArray(secondValue) ? [] : {},
|
||||
secondValue
|
||||
);
|
||||
} else if (!isUndefined(secondValue)) {
|
||||
result[key] = secondValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the rule options config for a given rule by ensuring that
|
||||
* it is an array and that the first item is 0, 1, or 2.
|
||||
* @param {Array|string|number} ruleOptions The rule options config.
|
||||
* @returns {Array} An array of rule options.
|
||||
*/
|
||||
function normalizeRuleOptions(ruleOptions) {
|
||||
|
||||
const finalOptions = Array.isArray(ruleOptions)
|
||||
? ruleOptions.slice(0)
|
||||
: [ruleOptions];
|
||||
|
||||
finalOptions[0] = ruleSeverities.get(finalOptions[0]);
|
||||
return finalOptions;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Assertions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Validates that a value is a valid rule options entry.
|
||||
* @param {any} value The value to check.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value isn't a valid rule options.
|
||||
*/
|
||||
function assertIsRuleOptions(value) {
|
||||
|
||||
if (typeof value !== "string" && typeof value !== "number" && !Array.isArray(value)) {
|
||||
throw new TypeError("Expected a string, number, or array.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is valid rule severity.
|
||||
* @param {any} value The value to check.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value isn't a valid rule severity.
|
||||
*/
|
||||
function assertIsRuleSeverity(value) {
|
||||
const severity = typeof value === "string"
|
||||
? ruleSeverities.get(value.toLowerCase())
|
||||
: ruleSeverities.get(value);
|
||||
|
||||
if (typeof severity === "undefined") {
|
||||
throw new TypeError("Expected severity of \"off\", 0, \"warn\", 1, \"error\", or 2.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a given string is the form pluginName/objectName.
|
||||
* @param {string} value The string to check.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the string isn't in the correct format.
|
||||
*/
|
||||
function assertIsPluginMemberName(value) {
|
||||
if (!/[@a-z0-9-_$]+(?:\/(?:[a-z0-9-_$]+))+$/iu.test(value)) {
|
||||
throw new TypeError(`Expected string in the form "pluginName/objectName" but found "${value}".`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is an object.
|
||||
* @param {any} value The value to check.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value isn't an object.
|
||||
*/
|
||||
function assertIsObject(value) {
|
||||
if (!isNonNullObject(value)) {
|
||||
throw new TypeError("Expected an object.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a value is an object or a string.
|
||||
* @param {any} value The value to check.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the value isn't an object or a string.
|
||||
*/
|
||||
function assertIsObjectOrString(value) {
|
||||
if ((!value || typeof value !== "object") && typeof value !== "string") {
|
||||
throw new TypeError("Expected an object or string.");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Low-Level Schemas
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const numberSchema = {
|
||||
merge: "replace",
|
||||
validate: "number"
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const booleanSchema = {
|
||||
merge: "replace",
|
||||
validate: "boolean"
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const deepObjectAssignSchema = {
|
||||
merge(first = {}, second = {}) {
|
||||
return deepMerge(first, second);
|
||||
},
|
||||
validate: "object"
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// High-Level Schemas
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const globalsSchema = {
|
||||
merge: "assign",
|
||||
validate(value) {
|
||||
|
||||
assertIsObject(value);
|
||||
|
||||
for (const key of Object.keys(value)) {
|
||||
|
||||
// avoid hairy edge case
|
||||
if (key === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key !== key.trim()) {
|
||||
throw new TypeError(`Global "${key}" has leading or trailing whitespace.`);
|
||||
}
|
||||
|
||||
if (!globalVariablesValues.has(value[key])) {
|
||||
throw new TypeError(`Key "${key}": Expected "readonly", "writable", or "off".`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const parserSchema = {
|
||||
merge: "replace",
|
||||
validate(value) {
|
||||
assertIsObjectOrString(value);
|
||||
|
||||
if (typeof value === "object" && typeof value.parse !== "function" && typeof value.parseForESLint !== "function") {
|
||||
throw new TypeError("Expected object to have a parse() or parseForESLint() method.");
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
assertIsPluginMemberName(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const pluginsSchema = {
|
||||
merge(first = {}, second = {}) {
|
||||
const keys = new Set([...Object.keys(first), ...Object.keys(second)]);
|
||||
const result = {};
|
||||
|
||||
// manually validate that plugins are not redefined
|
||||
for (const key of keys) {
|
||||
|
||||
// avoid hairy edge case
|
||||
if (key === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key in first && key in second && first[key] !== second[key]) {
|
||||
throw new TypeError(`Cannot redefine plugin "${key}".`);
|
||||
}
|
||||
|
||||
result[key] = second[key] || first[key];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
validate(value) {
|
||||
|
||||
// first check the value to be sure it's an object
|
||||
if (value === null || typeof value !== "object") {
|
||||
throw new TypeError("Expected an object.");
|
||||
}
|
||||
|
||||
// second check the keys to make sure they are objects
|
||||
for (const key of Object.keys(value)) {
|
||||
|
||||
// avoid hairy edge case
|
||||
if (key === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value[key] === null || typeof value[key] !== "object") {
|
||||
throw new TypeError(`Key "${key}": Expected an object.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const processorSchema = {
|
||||
merge: "replace",
|
||||
validate(value) {
|
||||
if (typeof value === "string") {
|
||||
assertIsPluginMemberName(value);
|
||||
} else if (value && typeof value === "object") {
|
||||
if (typeof value.preprocess !== "function" || typeof value.postprocess !== "function") {
|
||||
throw new TypeError("Object must have a preprocess() and a postprocess() method.");
|
||||
}
|
||||
} else {
|
||||
throw new TypeError("Expected an object or a string.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const rulesSchema = {
|
||||
merge(first = {}, second = {}) {
|
||||
|
||||
const result = {
|
||||
...first,
|
||||
...second
|
||||
};
|
||||
|
||||
for (const ruleId of Object.keys(result)) {
|
||||
|
||||
// avoid hairy edge case
|
||||
if (ruleId === "__proto__") {
|
||||
|
||||
/* eslint-disable-next-line no-proto */
|
||||
delete result.__proto__;
|
||||
continue;
|
||||
}
|
||||
|
||||
result[ruleId] = normalizeRuleOptions(result[ruleId]);
|
||||
|
||||
/*
|
||||
* If either rule config is missing, then the correct
|
||||
* config is already present and we just need to normalize
|
||||
* the severity.
|
||||
*/
|
||||
if (!(ruleId in first) || !(ruleId in second)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const firstRuleOptions = normalizeRuleOptions(first[ruleId]);
|
||||
const secondRuleOptions = normalizeRuleOptions(second[ruleId]);
|
||||
|
||||
/*
|
||||
* If the second rule config only has a severity (length of 1),
|
||||
* then use that severity and keep the rest of the options from
|
||||
* the first rule config.
|
||||
*/
|
||||
if (secondRuleOptions.length === 1) {
|
||||
result[ruleId] = [secondRuleOptions[0], ...firstRuleOptions.slice(1)];
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* In any other situation, then the second rule config takes
|
||||
* precedence. That means the value at `result[ruleId]` is
|
||||
* already correct and no further work is necessary.
|
||||
*/
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
validate(value) {
|
||||
assertIsObject(value);
|
||||
|
||||
let lastRuleId;
|
||||
|
||||
// Performance: One try-catch has less overhead than one per loop iteration
|
||||
try {
|
||||
|
||||
/*
|
||||
* We are not checking the rule schema here because there is no
|
||||
* guarantee that the rule definition is present at this point. Instead
|
||||
* we wait and check the rule schema during the finalization step
|
||||
* of calculating a config.
|
||||
*/
|
||||
for (const ruleId of Object.keys(value)) {
|
||||
|
||||
// avoid hairy edge case
|
||||
if (ruleId === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
|
||||
lastRuleId = ruleId;
|
||||
|
||||
const ruleOptions = value[ruleId];
|
||||
|
||||
assertIsRuleOptions(ruleOptions);
|
||||
|
||||
if (Array.isArray(ruleOptions)) {
|
||||
assertIsRuleSeverity(ruleOptions[0]);
|
||||
} else {
|
||||
assertIsRuleSeverity(ruleOptions);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
error.message = `Key "${lastRuleId}": ${error.message}`;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {ObjectPropertySchema} */
|
||||
const sourceTypeSchema = {
|
||||
merge: "replace",
|
||||
validate(value) {
|
||||
if (typeof value !== "string" || !/^(?:script|module|commonjs)$/u.test(value)) {
|
||||
throw new TypeError("Expected \"script\", \"module\", or \"commonjs\".");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Full schema
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
exports.flatConfigSchema = {
|
||||
settings: deepObjectAssignSchema,
|
||||
linterOptions: {
|
||||
schema: {
|
||||
noInlineConfig: booleanSchema,
|
||||
reportUnusedDisableDirectives: booleanSchema
|
||||
}
|
||||
},
|
||||
languageOptions: {
|
||||
schema: {
|
||||
ecmaVersion: numberSchema,
|
||||
sourceType: sourceTypeSchema,
|
||||
globals: globalsSchema,
|
||||
parser: parserSchema,
|
||||
parserOptions: deepObjectAssignSchema
|
||||
}
|
||||
},
|
||||
processor: processorSchema,
|
||||
plugins: pluginsSchema,
|
||||
rules: rulesSchema
|
||||
};
|
||||
169
node_modules/eslint/lib/config/rule-validator.js
generated
vendored
Normal file
169
node_modules/eslint/lib/config/rule-validator.js
generated
vendored
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/**
|
||||
* @fileoverview Rule Validator
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const ajv = require("../shared/ajv")();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Finds a rule with the given ID in the given config.
|
||||
* @param {string} ruleId The ID of the rule to find.
|
||||
* @param {Object} config The config to search in.
|
||||
* @returns {{create: Function, schema: (Array|null)}} THe rule object.
|
||||
*/
|
||||
function findRuleDefinition(ruleId, config) {
|
||||
const ruleIdParts = ruleId.split("/");
|
||||
let pluginName, ruleName;
|
||||
|
||||
// built-in rule
|
||||
if (ruleIdParts.length === 1) {
|
||||
pluginName = "@";
|
||||
ruleName = ruleIdParts[0];
|
||||
} else {
|
||||
ruleName = ruleIdParts.pop();
|
||||
pluginName = ruleIdParts.join("/");
|
||||
}
|
||||
|
||||
if (!config.plugins || !config.plugins[pluginName]) {
|
||||
throw new TypeError(`Key "rules": Key "${ruleId}": 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}".`);
|
||||
}
|
||||
|
||||
return config.plugins[pluginName].rules[ruleName];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Implements validation functionality for the rules portion of a config.
|
||||
*/
|
||||
class RuleValidator {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
/**
|
||||
* A collection of compiled validators for rules that have already
|
||||
* been validated.
|
||||
* @type {WeakMap}
|
||||
* @property validators
|
||||
*/
|
||||
this.validators = new WeakMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates all of the rule configurations in a config against each
|
||||
* rule's schema.
|
||||
* @param {Object} config The full config to validate. This object must
|
||||
* contain both the rules section and the plugins section.
|
||||
* @returns {void}
|
||||
* @throws {Error} If a rule's configuration does not match its schema.
|
||||
*/
|
||||
validate(config) {
|
||||
|
||||
if (!config.rules) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const [ruleId, ruleOptions] of Object.entries(config.rules)) {
|
||||
|
||||
// check for edge case
|
||||
if (ruleId === "__proto__") {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a rule is disabled, we don't do any validation. This allows
|
||||
* users to safely set any value to 0 or "off" without worrying
|
||||
* that it will cause a validation error.
|
||||
*
|
||||
* Note: ruleOptions is always an array at this point because
|
||||
* this validation occurs after FlatConfigArray has merged and
|
||||
* normalized values.
|
||||
*/
|
||||
if (ruleOptions[0] === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const rule = findRuleDefinition(ruleId, config);
|
||||
|
||||
// Precompile and cache validator the first time
|
||||
if (!this.validators.has(rule)) {
|
||||
const schema = getRuleOptionsSchema(rule);
|
||||
|
||||
if (schema) {
|
||||
this.validators.set(rule, ajv.compile(schema));
|
||||
}
|
||||
}
|
||||
|
||||
const validateRule = this.validators.get(rule);
|
||||
|
||||
if (validateRule) {
|
||||
|
||||
validateRule(ruleOptions.slice(1));
|
||||
|
||||
if (validateRule.errors) {
|
||||
throw new Error(`Key "rules": Key "${ruleId}": ${
|
||||
validateRule.errors.map(
|
||||
error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n`
|
||||
).join("")
|
||||
}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.RuleValidator = RuleValidator;
|
||||
53
node_modules/eslint/lib/eslint/eslint.js
generated
vendored
53
node_modules/eslint/lib/eslint/eslint.js
generated
vendored
|
|
@ -43,6 +43,7 @@ const { version } = require("../../package.json");
|
|||
* @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this instance
|
||||
* @property {boolean} [cache] Enable result caching.
|
||||
* @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
|
||||
* @property {"metadata" | "content"} [cacheStrategy] The strategy used to detect changed files.
|
||||
* @property {string} [cwd] The value to use for the current working directory.
|
||||
* @property {boolean} [errorOnUnmatchedPattern] If `false` then `ESLint#lintFiles()` doesn't throw even if no target files found. Defaults to `true`.
|
||||
* @property {string[]} [extensions] An array of file extensions to check.
|
||||
|
|
@ -157,6 +158,7 @@ function processOptions({
|
|||
baseConfig = null,
|
||||
cache = false,
|
||||
cacheLocation = ".eslintcache",
|
||||
cacheStrategy = "metadata",
|
||||
cwd = process.cwd(),
|
||||
errorOnUnmatchedPattern = true,
|
||||
extensions = null, // ← should be null by default because if it's an array then it suppresses RFC20 feature.
|
||||
|
|
@ -216,6 +218,12 @@ function processOptions({
|
|||
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.");
|
||||
}
|
||||
|
|
@ -272,7 +280,7 @@ function processOptions({
|
|||
errors.push("'rulePaths' must be an array of non-empty strings.");
|
||||
}
|
||||
if (typeof useEslintrc !== "boolean") {
|
||||
errors.push("'useElintrc' must be a boolean.");
|
||||
errors.push("'useEslintrc' must be a boolean.");
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
|
|
@ -284,6 +292,7 @@ function processOptions({
|
|||
baseConfig,
|
||||
cache,
|
||||
cacheLocation,
|
||||
cacheStrategy,
|
||||
configFile: overrideConfigFile,
|
||||
cwd,
|
||||
errorOnUnmatchedPattern,
|
||||
|
|
@ -505,6 +514,39 @@ class ESLint {
|
|||
return CLIEngine.getErrorResults(results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns meta objects for each rule represented in the lint results.
|
||||
* @param {LintResult[]} results The results to fetch rules meta for.
|
||||
* @returns {Object} A mapping of ruleIds to rule meta objects.
|
||||
*/
|
||||
getRulesMetaForResults(results) {
|
||||
|
||||
const resultRuleIds = new Set();
|
||||
|
||||
// first gather all ruleIds from all results
|
||||
|
||||
for (const result of results) {
|
||||
for (const { ruleId } of result.messages) {
|
||||
resultRuleIds.add(ruleId);
|
||||
}
|
||||
}
|
||||
|
||||
// create a map of all rules in the results
|
||||
|
||||
const { cliEngine } = privateMembersMap.get(this);
|
||||
const rules = cliEngine.getRules();
|
||||
const resultRules = new Map();
|
||||
|
||||
for (const [ruleId, rule] of rules) {
|
||||
if (resultRuleIds.has(ruleId)) {
|
||||
resultRules.set(ruleId, rule);
|
||||
}
|
||||
}
|
||||
|
||||
return createRulesMeta(resultRules);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the current configuration on an array of file and directory names.
|
||||
* @param {string[]} patterns An array of file and directory names.
|
||||
|
|
@ -543,9 +585,12 @@ class ESLint {
|
|||
...unknownOptions
|
||||
} = options || {};
|
||||
|
||||
for (const key of Object.keys(unknownOptions)) {
|
||||
throw new Error(`'options' must not include the unknown option '${key}'`);
|
||||
const unknownOptionKeys = Object.keys(unknownOptions);
|
||||
|
||||
if (unknownOptionKeys.length > 0) {
|
||||
throw new Error(`'options' must not include the unknown option(s): ${unknownOptionKeys.join(", ")}`);
|
||||
}
|
||||
|
||||
if (filePath !== void 0 && !isNonEmptyString(filePath)) {
|
||||
throw new Error("'options.filePath' must be a non-empty string or undefined");
|
||||
}
|
||||
|
|
@ -563,7 +608,7 @@ class ESLint {
|
|||
|
||||
/**
|
||||
* Returns the formatter representing the given formatter name.
|
||||
* @param {string} [name] The name of the formattter to load.
|
||||
* @param {string} [name] The name of the formatter to load.
|
||||
* The following values are allowed:
|
||||
* - `undefined` ... Load `stylish` builtin formatter.
|
||||
* - A builtin formatter name ... Load the builtin formatter.
|
||||
|
|
|
|||
6
node_modules/eslint/lib/init/autoconfig.js
generated
vendored
6
node_modules/eslint/lib/init/autoconfig.js
generated
vendored
|
|
@ -9,7 +9,7 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash"),
|
||||
const equal = require("fast-deep-equal"),
|
||||
recConfig = require("../../conf/eslint-recommended"),
|
||||
ConfigOps = require("@eslint/eslintrc/lib/shared/config-ops"),
|
||||
{ Linter } = require("../linter"),
|
||||
|
|
@ -85,7 +85,7 @@ class Registry {
|
|||
* @returns {void}
|
||||
*/
|
||||
populateFromCoreRules() {
|
||||
const rulesConfig = configRule.createCoreRuleConfigs();
|
||||
const rulesConfig = configRule.createCoreRuleConfigs(/* noDeprecated = */ true);
|
||||
|
||||
this.rules = makeRegistryItems(rulesConfig);
|
||||
}
|
||||
|
|
@ -329,7 +329,7 @@ function extendFromRecommended(config) {
|
|||
const recRules = Object.keys(recConfig.rules).filter(ruleId => ConfigOps.isErrorSeverity(recConfig.rules[ruleId]));
|
||||
|
||||
recRules.forEach(ruleId => {
|
||||
if (lodash.isEqual(recConfig.rules[ruleId], newConfig.rules[ruleId])) {
|
||||
if (equal(recConfig.rules[ruleId], newConfig.rules[ruleId])) {
|
||||
delete newConfig.rules[ruleId];
|
||||
}
|
||||
});
|
||||
|
|
|
|||
1
node_modules/eslint/lib/init/config-file.js
generated
vendored
1
node_modules/eslint/lib/init/config-file.js
generated
vendored
|
|
@ -117,6 +117,7 @@ function writeJSConfigFile(config, filePath) {
|
|||
function write(config, filePath) {
|
||||
switch (path.extname(filePath)) {
|
||||
case ".js":
|
||||
case ".cjs":
|
||||
writeJSConfigFile(config, filePath);
|
||||
break;
|
||||
|
||||
|
|
|
|||
18
node_modules/eslint/lib/init/config-initializer.js
generated
vendored
18
node_modules/eslint/lib/init/config-initializer.js
generated
vendored
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
const util = require("util"),
|
||||
path = require("path"),
|
||||
fs = require("fs"),
|
||||
enquirer = require("enquirer"),
|
||||
ProgressBar = require("progress"),
|
||||
semver = require("semver"),
|
||||
|
|
@ -48,6 +49,16 @@ function writeFile(config, format) {
|
|||
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;
|
||||
|
|
@ -531,7 +542,8 @@ function promptUser() {
|
|||
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: "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();
|
||||
|
|
@ -565,7 +577,8 @@ function promptUser() {
|
|||
{
|
||||
type: "toggle",
|
||||
name: "installESLint",
|
||||
message(answers) {
|
||||
message() {
|
||||
const { answers } = this.state;
|
||||
const verb = semver.ltr(answers.localESLintVersion, answers.requiredESLintVersionRange)
|
||||
? "upgrade"
|
||||
: "downgrade";
|
||||
|
|
@ -682,6 +695,7 @@ const init = {
|
|||
hasESLintVersionConflict,
|
||||
installModules,
|
||||
processAnswers,
|
||||
writeFile,
|
||||
/* istanbul ignore next */initializeConfig() {
|
||||
return promptUser();
|
||||
}
|
||||
|
|
|
|||
4
node_modules/eslint/lib/init/npm-utils.js
generated
vendored
4
node_modules/eslint/lib/init/npm-utils.js
generated
vendored
|
|
@ -50,8 +50,7 @@ function findPackageJson(startDir) {
|
|||
*/
|
||||
function installSyncSaveDev(packages) {
|
||||
const packageList = Array.isArray(packages) ? packages : [packages];
|
||||
const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList),
|
||||
{ stdio: "inherit" });
|
||||
const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList), { stdio: "inherit" });
|
||||
const error = npmProcess.error;
|
||||
|
||||
if (error && error.code === "ENOENT") {
|
||||
|
|
@ -172,6 +171,7 @@ function checkPackageJson(startDir) {
|
|||
module.exports = {
|
||||
installSyncSaveDev,
|
||||
fetchPeerDependencies,
|
||||
findPackageJson,
|
||||
checkDeps,
|
||||
checkDevDeps,
|
||||
checkPackageJson
|
||||
|
|
|
|||
18
node_modules/eslint/lib/linter/apply-disable-directives.js
generated
vendored
18
node_modules/eslint/lib/linter/apply-disable-directives.js
generated
vendored
|
|
@ -5,8 +5,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const lodash = require("lodash");
|
||||
|
||||
/**
|
||||
* Compares the locations of two objects in a source file
|
||||
* @param {{line: number, column: number}} itemA The first object
|
||||
|
|
@ -124,7 +122,21 @@ module.exports = ({ directives, problems, reportUnusedDisableDirectives = "off"
|
|||
.map(directive => Object.assign({}, directive, { unprocessedDirective: directive }))
|
||||
.sort(compareLocations);
|
||||
|
||||
const lineDirectives = lodash.flatMap(directives, directive => {
|
||||
/**
|
||||
* 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 => {
|
||||
switch (directive.type) {
|
||||
case "disable":
|
||||
case "enable":
|
||||
|
|
|
|||
62
node_modules/eslint/lib/linter/linter.js
generated
vendored
62
node_modules/eslint/lib/linter/linter.js
generated
vendored
|
|
@ -15,7 +15,7 @@ const
|
|||
eslintScope = require("eslint-scope"),
|
||||
evk = require("eslint-visitor-keys"),
|
||||
espree = require("espree"),
|
||||
lodash = require("lodash"),
|
||||
merge = require("lodash.merge"),
|
||||
BuiltInEnvironments = require("@eslint/eslintrc/conf/environments"),
|
||||
pkg = require("../../package.json"),
|
||||
astUtils = require("../shared/ast-utils"),
|
||||
|
|
@ -37,8 +37,10 @@ const
|
|||
const debug = require("debug")("eslint:linter");
|
||||
const MAX_AUTOFIX_PASSES = 10;
|
||||
const DEFAULT_PARSER_NAME = "espree";
|
||||
const DEFAULT_ECMA_VERSION = 5;
|
||||
const commentParser = new ConfigCommentParser();
|
||||
const DEFAULT_ERROR_LOC = { start: { line: 1, column: 0 }, end: { line: 1, column: 1 } };
|
||||
const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Typedefs
|
||||
|
|
@ -432,10 +434,16 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
|
|||
|
||||
/**
|
||||
* Normalize ECMAScript version from the initial config
|
||||
* @param {number} ecmaVersion ECMAScript version from the initial config
|
||||
* @param {Parser} parser The parser which uses this options.
|
||||
* @param {number} ecmaVersion ECMAScript version from the initial config
|
||||
* @returns {number} normalized ECMAScript version
|
||||
*/
|
||||
function normalizeEcmaVersion(ecmaVersion) {
|
||||
function normalizeEcmaVersion(parser, ecmaVersion) {
|
||||
if ((parser[parserSymbol] || parser) === espree) {
|
||||
if (ecmaVersion === "latest") {
|
||||
return espree.latestEcmaVersion;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate ECMAScript edition number from official year version starting with
|
||||
|
|
@ -444,7 +452,7 @@ function normalizeEcmaVersion(ecmaVersion) {
|
|||
return ecmaVersion >= 2015 ? ecmaVersion - 2009 : ecmaVersion;
|
||||
}
|
||||
|
||||
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//gu;
|
||||
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//gsu;
|
||||
|
||||
/**
|
||||
* Checks whether or not there is a comment which has "eslint-env *" in a given text.
|
||||
|
|
@ -521,16 +529,17 @@ function normalizeVerifyOptions(providedOptions, config) {
|
|||
|
||||
/**
|
||||
* Combines the provided parserOptions with the options from environments
|
||||
* @param {string} parserName The parser name which uses this options.
|
||||
* @param {Parser} parser The parser which uses this options.
|
||||
* @param {ParserOptions} providedOptions The provided 'parserOptions' key in a config
|
||||
* @param {Environment[]} enabledEnvironments The environments enabled in configuration and with inline comments
|
||||
* @returns {ParserOptions} Resulting parser options after merge
|
||||
*/
|
||||
function resolveParserOptions(parserName, providedOptions, enabledEnvironments) {
|
||||
function resolveParserOptions(parser, providedOptions, enabledEnvironments) {
|
||||
|
||||
const parserOptionsFromEnv = enabledEnvironments
|
||||
.filter(env => env.parserOptions)
|
||||
.reduce((parserOptions, env) => lodash.merge(parserOptions, env.parserOptions), {});
|
||||
const mergedParserOptions = lodash.merge(parserOptionsFromEnv, providedOptions || {});
|
||||
.reduce((parserOptions, env) => merge(parserOptions, env.parserOptions), {});
|
||||
const mergedParserOptions = merge(parserOptionsFromEnv, providedOptions || {});
|
||||
const isModule = mergedParserOptions.sourceType === "module";
|
||||
|
||||
if (isModule) {
|
||||
|
|
@ -542,12 +551,7 @@ function resolveParserOptions(parserName, providedOptions, enabledEnvironments)
|
|||
mergedParserOptions.ecmaFeatures = Object.assign({}, mergedParserOptions.ecmaFeatures, { globalReturn: false });
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: @aladdin-add
|
||||
* 1. for a 3rd-party parser, do not normalize parserOptions
|
||||
* 2. for espree, no need to do this (espree will do it)
|
||||
*/
|
||||
mergedParserOptions.ecmaVersion = normalizeEcmaVersion(mergedParserOptions.ecmaVersion);
|
||||
mergedParserOptions.ecmaVersion = normalizeEcmaVersion(parser, mergedParserOptions.ecmaVersion);
|
||||
|
||||
return mergedParserOptions;
|
||||
}
|
||||
|
|
@ -606,7 +610,7 @@ function getRuleOptions(ruleConfig) {
|
|||
*/
|
||||
function analyzeScope(ast, parserOptions, visitorKeys) {
|
||||
const ecmaFeatures = parserOptions.ecmaFeatures || {};
|
||||
const ecmaVersion = parserOptions.ecmaVersion || 5;
|
||||
const ecmaVersion = parserOptions.ecmaVersion || DEFAULT_ECMA_VERSION;
|
||||
|
||||
return eslintScope.analyze(ast, {
|
||||
ignoreEval: true,
|
||||
|
|
@ -828,9 +832,10 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
|
|||
* @param {string} filename The reported filename of the code
|
||||
* @param {boolean} disableFixes If true, it doesn't make `fix` properties.
|
||||
* @param {string | undefined} cwd cwd of the cli
|
||||
* @param {string} physicalFilename The full path of the file on disk without any code block information
|
||||
* @returns {Problem[]} An array of reported problems
|
||||
*/
|
||||
function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename, disableFixes, cwd) {
|
||||
function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename, disableFixes, cwd, physicalFilename) {
|
||||
const emitter = createEmitter();
|
||||
const nodeQueue = [];
|
||||
let currentNode = sourceCode.ast;
|
||||
|
|
@ -859,6 +864,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
|
|||
getDeclaredVariables: sourceCode.scopeManager.getDeclaredVariables.bind(sourceCode.scopeManager),
|
||||
getCwd: () => cwd,
|
||||
getFilename: () => filename,
|
||||
getPhysicalFilename: () => physicalFilename || filename,
|
||||
getScope: () => getScope(sourceCode.scopeManager, currentNode),
|
||||
getSourceCode: () => sourceCode,
|
||||
markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode, parserOptions, name),
|
||||
|
|
@ -942,7 +948,9 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
|
|||
});
|
||||
|
||||
// only run code path analyzer if the top level node is "Program", skip otherwise
|
||||
const eventGenerator = nodeQueue[0].node.type === "Program" ? new CodePathAnalyzer(new NodeEventGenerator(emitter)) : new NodeEventGenerator(emitter);
|
||||
const eventGenerator = nodeQueue[0].node.type === "Program"
|
||||
? new CodePathAnalyzer(new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys }))
|
||||
: new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys });
|
||||
|
||||
nodeQueue.forEach(traversalInfo => {
|
||||
currentNode = traversalInfo.node;
|
||||
|
|
@ -1119,7 +1127,7 @@ class Linter {
|
|||
.map(envName => getEnv(slots, envName))
|
||||
.filter(env => env);
|
||||
|
||||
const parserOptions = resolveParserOptions(parserName, config.parserOptions || {}, enabledEnvs);
|
||||
const parserOptions = resolveParserOptions(parser, config.parserOptions || {}, enabledEnvs);
|
||||
const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs);
|
||||
const settings = config.settings || {};
|
||||
|
||||
|
|
@ -1179,7 +1187,8 @@ class Linter {
|
|||
settings,
|
||||
options.filename,
|
||||
options.disableFixes,
|
||||
slots.cwd
|
||||
slots.cwd,
|
||||
providedOptions.physicalFilename
|
||||
);
|
||||
} catch (err) {
|
||||
err.message += `\nOccurred while linting ${options.filename}`;
|
||||
|
|
@ -1282,9 +1291,12 @@ class Linter {
|
|||
_verifyWithProcessor(textOrSourceCode, config, options, configForRecursive) {
|
||||
const filename = options.filename || "<input>";
|
||||
const filenameToExpose = normalizeFilename(filename);
|
||||
const physicalFilename = options.physicalFilename || filenameToExpose;
|
||||
const text = ensureText(textOrSourceCode);
|
||||
const preprocess = options.preprocess || (rawText => [rawText]);
|
||||
const postprocess = options.postprocess || lodash.flatten;
|
||||
|
||||
// TODO(stephenwade): Replace this with array.flat() when we drop support for Node v10
|
||||
const postprocess = options.postprocess || (array => [].concat(...array));
|
||||
const filterCodeBlock =
|
||||
options.filterCodeBlock ||
|
||||
(blockFilename => blockFilename.endsWith(".js"));
|
||||
|
|
@ -1306,13 +1318,13 @@ class Linter {
|
|||
return [];
|
||||
}
|
||||
|
||||
// Resolve configuration again if the file extension was changed.
|
||||
if (configForRecursive && path.extname(blockName) !== originalExtname) {
|
||||
debug("Resolving configuration again because the file extension was changed.");
|
||||
// Resolve configuration again if the file content or extension was changed.
|
||||
if (configForRecursive && (text !== blockText || path.extname(blockName) !== originalExtname)) {
|
||||
debug("Resolving configuration again because the file content or extension was changed.");
|
||||
return this._verifyWithConfigArray(
|
||||
blockText,
|
||||
configForRecursive,
|
||||
{ ...options, filename: blockName }
|
||||
{ ...options, filename: blockName, physicalFilename }
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1320,7 +1332,7 @@ class Linter {
|
|||
return this._verifyWithoutProcessors(
|
||||
blockText,
|
||||
config,
|
||||
{ ...options, filename: blockName }
|
||||
{ ...options, filename: blockName, physicalFilename }
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
55
node_modules/eslint/lib/linter/node-event-generator.js
generated
vendored
55
node_modules/eslint/lib/linter/node-event-generator.js
generated
vendored
|
|
@ -10,7 +10,6 @@
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
const esquery = require("esquery");
|
||||
const lodash = require("lodash");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Typedefs
|
||||
|
|
@ -32,6 +31,35 @@ const lodash = require("lodash");
|
|||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Computes the union of one or more arrays
|
||||
* @param {...any[]} arrays One or more arrays to union
|
||||
* @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))];
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the intersection of one or more arrays
|
||||
* @param {...any[]} arrays One or more arrays to intersect
|
||||
* @returns {any[]} The intersection of the input arrays
|
||||
*/
|
||||
function intersection(...arrays) {
|
||||
if (arrays.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let result = [...new Set(arrays[0])];
|
||||
|
||||
for (const array of arrays.slice(1)) {
|
||||
result = result.filter(x => array.includes(x));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the possible types of a selector
|
||||
* @param {Object} parsedSelector An object (from esquery) describing the matching behavior of the selector
|
||||
|
|
@ -46,7 +74,7 @@ function getPossibleTypes(parsedSelector) {
|
|||
const typesForComponents = parsedSelector.selectors.map(getPossibleTypes);
|
||||
|
||||
if (typesForComponents.every(Boolean)) {
|
||||
return lodash.union(...typesForComponents);
|
||||
return union(...typesForComponents);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -63,7 +91,7 @@ function getPossibleTypes(parsedSelector) {
|
|||
* If at least one of the components could only match a particular type, the compound could only match
|
||||
* the intersection of those types.
|
||||
*/
|
||||
return lodash.intersection(...typesForComponents);
|
||||
return intersection(...typesForComponents);
|
||||
}
|
||||
|
||||
case "child":
|
||||
|
|
@ -166,15 +194,21 @@ function tryParseSelector(rawSelector) {
|
|||
}
|
||||
}
|
||||
|
||||
const selectorCache = new Map();
|
||||
|
||||
/**
|
||||
* Parses a raw selector string, and returns the parsed selector along with specificity and type information.
|
||||
* @param {string} rawSelector A raw AST selector
|
||||
* @returns {ASTSelector} A selector descriptor
|
||||
*/
|
||||
const parseSelector = lodash.memoize(rawSelector => {
|
||||
function parseSelector(rawSelector) {
|
||||
if (selectorCache.has(rawSelector)) {
|
||||
return selectorCache.get(rawSelector);
|
||||
}
|
||||
|
||||
const parsedSelector = tryParseSelector(rawSelector);
|
||||
|
||||
return {
|
||||
const result = {
|
||||
rawSelector,
|
||||
isExit: rawSelector.endsWith(":exit"),
|
||||
parsedSelector,
|
||||
|
|
@ -182,7 +216,10 @@ const parseSelector = lodash.memoize(rawSelector => {
|
|||
attributeCount: countClassAttributes(parsedSelector),
|
||||
identifierCount: countIdentifiers(parsedSelector)
|
||||
};
|
||||
});
|
||||
|
||||
selectorCache.set(rawSelector, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
|
|
@ -208,10 +245,12 @@ class NodeEventGenerator {
|
|||
* An SafeEmitter which is the destination of events. This emitter must already
|
||||
* have registered listeners for all of the events that it needs to listen for.
|
||||
* (See lib/linter/safe-emitter.js for more details on `SafeEmitter`.)
|
||||
* @param {ESQueryOptions} esqueryOptions `esquery` options for traversing custom nodes.
|
||||
* @returns {NodeEventGenerator} new instance
|
||||
*/
|
||||
constructor(emitter) {
|
||||
constructor(emitter, esqueryOptions) {
|
||||
this.emitter = emitter;
|
||||
this.esqueryOptions = esqueryOptions;
|
||||
this.currentAncestry = [];
|
||||
this.enterSelectorsByNodeType = new Map();
|
||||
this.exitSelectorsByNodeType = new Map();
|
||||
|
|
@ -250,7 +289,7 @@ class NodeEventGenerator {
|
|||
* @returns {void}
|
||||
*/
|
||||
applySelector(node, selector) {
|
||||
if (esquery.matches(node, selector.parsedSelector, this.currentAncestry)) {
|
||||
if (esquery.matches(node, selector.parsedSelector, this.currentAncestry, this.esqueryOptions)) {
|
||||
this.emitter.emit(selector.rawSelector, node);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
37
node_modules/eslint/lib/linter/report-translator.js
generated
vendored
37
node_modules/eslint/lib/linter/report-translator.js
generated
vendored
|
|
@ -115,6 +115,17 @@ function normalizeReportLoc(descriptor) {
|
|||
return descriptor.node.loc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a fix has a valid range.
|
||||
* @param {Fix|null} fix The fix to validate.
|
||||
* @returns {void}
|
||||
*/
|
||||
function assertValidFix(fix) {
|
||||
if (fix) {
|
||||
assert(fix.range && typeof fix.range[0] === "number" && typeof fix.range[1] === "number", `Fix has invalid range: ${JSON.stringify(fix, null, 2)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares items in a fixes array by range.
|
||||
* @param {Fix} a The first message.
|
||||
|
|
@ -133,6 +144,10 @@ function compareFixesByRange(a, b) {
|
|||
* @returns {{text: string, range: number[]}} The merged fixes
|
||||
*/
|
||||
function mergeFixes(fixes, sourceCode) {
|
||||
for (const fix of fixes) {
|
||||
assertValidFix(fix);
|
||||
}
|
||||
|
||||
if (fixes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -181,6 +196,8 @@ function normalizeFixes(descriptor, sourceCode) {
|
|||
if (fix && Symbol.iterator in fix) {
|
||||
return mergeFixes(Array.from(fix), sourceCode);
|
||||
}
|
||||
|
||||
assertValidFix(fix);
|
||||
return fix;
|
||||
}
|
||||
|
||||
|
|
@ -196,15 +213,19 @@ function mapSuggestions(descriptor, sourceCode, messages) {
|
|||
return [];
|
||||
}
|
||||
|
||||
return descriptor.suggest.map(suggestInfo => {
|
||||
const computedDesc = suggestInfo.desc || messages[suggestInfo.messageId];
|
||||
return descriptor.suggest
|
||||
.map(suggestInfo => {
|
||||
const computedDesc = suggestInfo.desc || messages[suggestInfo.messageId];
|
||||
|
||||
return {
|
||||
...suggestInfo,
|
||||
desc: interpolate(computedDesc, suggestInfo.data),
|
||||
fix: normalizeFixes(suggestInfo, sourceCode)
|
||||
};
|
||||
});
|
||||
return {
|
||||
...suggestInfo,
|
||||
desc: interpolate(computedDesc, suggestInfo.data),
|
||||
fix: normalizeFixes(suggestInfo, sourceCode)
|
||||
};
|
||||
})
|
||||
|
||||
// Remove suggestions that didn't provide a fix
|
||||
.filter(({ fix }) => fix);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
25
node_modules/eslint/lib/linter/timing.js
generated
vendored
25
node_modules/eslint/lib/linter/timing.js
generated
vendored
|
|
@ -44,6 +44,26 @@ const enabled = !!process.env.TIMING;
|
|||
const HEADERS = ["Rule", "Time (ms)", "Relative"];
|
||||
const ALIGN = [alignLeft, alignRight, alignRight];
|
||||
|
||||
/**
|
||||
* Decide how many rules to show in the output list.
|
||||
* @returns {number} the number of rules to show
|
||||
*/
|
||||
function getListSize() {
|
||||
const MINIMUM_SIZE = 10;
|
||||
|
||||
if (typeof process.env.TIMING !== "string") {
|
||||
return MINIMUM_SIZE;
|
||||
}
|
||||
|
||||
if (process.env.TIMING.toLowerCase() === "all") {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
const TIMING_ENV_VAR_AS_INTEGER = Number.parseInt(process.env.TIMING, 10);
|
||||
|
||||
return TIMING_ENV_VAR_AS_INTEGER > 10 ? TIMING_ENV_VAR_AS_INTEGER : MINIMUM_SIZE;
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
/**
|
||||
* display the data
|
||||
|
|
@ -61,7 +81,7 @@ function display(data) {
|
|||
return [key, time];
|
||||
})
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.slice(0, 10);
|
||||
.slice(0, getListSize());
|
||||
|
||||
rows.forEach(row => {
|
||||
row.push(`${(row[1] * 100 / total).toFixed(1)}%`);
|
||||
|
|
@ -133,7 +153,8 @@ module.exports = (function() {
|
|||
|
||||
return {
|
||||
time,
|
||||
enabled
|
||||
enabled,
|
||||
getListSize
|
||||
};
|
||||
|
||||
}());
|
||||
|
|
|
|||
55
node_modules/eslint/lib/options.js
generated
vendored
55
node_modules/eslint/lib/options.js
generated
vendored
|
|
@ -11,6 +11,53 @@
|
|||
|
||||
const optionator = require("optionator");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Typedefs
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The options object parsed by Optionator.
|
||||
* @typedef {Object} ParsedCLIOptions
|
||||
* @property {boolean} cache Only check changed files
|
||||
* @property {string} cacheFile Path to the cache file. Deprecated: use --cache-location
|
||||
* @property {string} [cacheLocation] Path to the cache file or directory
|
||||
* @property {"metadata" | "content"} cacheStrategy Strategy to use for detecting changed files in the cache
|
||||
* @property {boolean} [color] Force enabling/disabling of color
|
||||
* @property {string} [config] Use this configuration, overriding .eslintrc.* config options if present
|
||||
* @property {boolean} debug Output debugging information
|
||||
* @property {string[]} [env] Specify environments
|
||||
* @property {boolean} envInfo Output execution environment information
|
||||
* @property {boolean} errorOnUnmatchedPattern Prevent errors when pattern is unmatched
|
||||
* @property {boolean} eslintrc Disable use of configuration from .eslintrc.*
|
||||
* @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 {string} format Use a specific output format
|
||||
* @property {string[]} [global] Define global variables
|
||||
* @property {boolean} [help] Show help
|
||||
* @property {boolean} ignore Disable use of ignore files and patterns
|
||||
* @property {string} [ignorePath] Specify path of ignore file
|
||||
* @property {string[]} [ignorePattern] Pattern of files to ignore (in addition to those in .eslintignore)
|
||||
* @property {boolean} init Run config initialization wizard
|
||||
* @property {boolean} inlineConfig Prevent comments from changing config or rules
|
||||
* @property {number} maxWarnings Number of warnings to trigger nonzero exit code
|
||||
* @property {string} [outputFile] Specify file to write report to
|
||||
* @property {string} [parser] Specify the parser to be used
|
||||
* @property {Object} [parserOptions] Specify parser options
|
||||
* @property {string[]} [plugin] Specify plugins
|
||||
* @property {string} [printConfig] Print the configuration for the given file
|
||||
* @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 {boolean} stdin Lint code provided on <STDIN>
|
||||
* @property {string} [stdinFilename] Specify filename to process STDIN as
|
||||
* @property {boolean} quiet Report errors only
|
||||
* @property {boolean} [version] Output the version number
|
||||
* @property {string[]} _ Positional filenames or patterns
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Initialization and Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -214,6 +261,14 @@ module.exports = optionator({
|
|||
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"
|
||||
},
|
||||
|
|
|
|||
116
node_modules/eslint/lib/rule-tester/rule-tester.js
generated
vendored
116
node_modules/eslint/lib/rule-tester/rule-tester.js
generated
vendored
|
|
@ -44,7 +44,8 @@ const
|
|||
assert = require("assert"),
|
||||
path = require("path"),
|
||||
util = require("util"),
|
||||
lodash = require("lodash"),
|
||||
merge = require("lodash.merge"),
|
||||
equal = require("fast-deep-equal"),
|
||||
Traverser = require("../../lib/shared/traverser"),
|
||||
{ getRuleOptionsSchema, validate } = require("../shared/config-validator"),
|
||||
{ Linter, SourceCodeFixer, interpolate } = require("../linter");
|
||||
|
|
@ -52,6 +53,7 @@ const
|
|||
const ajv = require("../shared/ajv")({ strictDefaults: true });
|
||||
|
||||
const espreePath = require.resolve("espree");
|
||||
const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Typedefs
|
||||
|
|
@ -70,6 +72,7 @@ const espreePath = require.resolve("espree");
|
|||
* @property {{ [name: string]: any }} [parserOptions] Options for the parser.
|
||||
* @property {{ [name: string]: "readonly" | "writable" | "off" }} [globals] The additional global variables.
|
||||
* @property {{ [name: string]: boolean }} [env] Environments for the test case.
|
||||
* @property {boolean} [only] Run only this test case or the subset of test cases with this property.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -85,6 +88,7 @@ const espreePath = require.resolve("espree");
|
|||
* @property {{ [name: string]: any }} [parserOptions] Options for the parser.
|
||||
* @property {{ [name: string]: "readonly" | "writable" | "off" }} [globals] The additional global variables.
|
||||
* @property {{ [name: string]: boolean }} [env] Environments for the test case.
|
||||
* @property {boolean} [only] Run only this test case or the subset of test cases with this property.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -120,7 +124,8 @@ const RuleTesterParameters = [
|
|||
"filename",
|
||||
"options",
|
||||
"errors",
|
||||
"output"
|
||||
"output",
|
||||
"only"
|
||||
];
|
||||
|
||||
/*
|
||||
|
|
@ -235,6 +240,7 @@ function defineStartEndAsError(objName, node) {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Define `start`/`end` properties of all nodes of the given AST as throwing error.
|
||||
* @param {ASTNode} ast The root node to errorize `start`/`end` properties.
|
||||
|
|
@ -254,8 +260,10 @@ function defineStartEndAsErrorInTree(ast, visitorKeys) {
|
|||
* @returns {Parser} Wrapped parser object.
|
||||
*/
|
||||
function wrapParser(parser) {
|
||||
|
||||
if (typeof parser.parseForESLint === "function") {
|
||||
return {
|
||||
[parserSymbol]: parser,
|
||||
parseForESLint(...args) {
|
||||
const ret = parser.parseForESLint(...args);
|
||||
|
||||
|
|
@ -264,7 +272,9 @@ function wrapParser(parser) {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
[parserSymbol]: parser,
|
||||
parse(...args) {
|
||||
const ast = parser.parse(...args);
|
||||
|
||||
|
|
@ -281,6 +291,7 @@ function wrapParser(parser) {
|
|||
// default separators for testing
|
||||
const DESCRIBE = Symbol("describe");
|
||||
const IT = Symbol("it");
|
||||
const IT_ONLY = Symbol("itOnly");
|
||||
|
||||
/**
|
||||
* This is `it` default handler if `it` don't exist.
|
||||
|
|
@ -324,10 +335,9 @@ class RuleTester {
|
|||
* configuration and the default configuration.
|
||||
* @type {Object}
|
||||
*/
|
||||
this.testerConfig = lodash.merge(
|
||||
|
||||
// we have to clone because merge uses the first argument for recipient
|
||||
lodash.cloneDeep(defaultConfig),
|
||||
this.testerConfig = merge(
|
||||
{},
|
||||
defaultConfig,
|
||||
testerConfig,
|
||||
{ rules: { "rule-tester/validate-ast": "error" } }
|
||||
);
|
||||
|
|
@ -369,7 +379,7 @@ class RuleTester {
|
|||
* @returns {void}
|
||||
*/
|
||||
static resetDefaultConfig() {
|
||||
defaultConfig = lodash.cloneDeep(testerDefaultConfig);
|
||||
defaultConfig = merge({}, testerDefaultConfig);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -400,6 +410,46 @@ class RuleTester {
|
|||
this[IT] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the `only` property to a test to run it in isolation.
|
||||
* @param {string | ValidTestCase | InvalidTestCase} item A single test to run by itself.
|
||||
* @returns {ValidTestCase | InvalidTestCase} The test with `only` set.
|
||||
*/
|
||||
static only(item) {
|
||||
if (typeof item === "string") {
|
||||
return { code: item, only: true };
|
||||
}
|
||||
|
||||
return { ...item, only: true };
|
||||
}
|
||||
|
||||
static get itOnly() {
|
||||
if (typeof this[IT_ONLY] === "function") {
|
||||
return this[IT_ONLY];
|
||||
}
|
||||
if (typeof this[IT] === "function" && typeof this[IT].only === "function") {
|
||||
return Function.bind.call(this[IT].only, this[IT]);
|
||||
}
|
||||
if (typeof it === "function" && typeof it.only === "function") {
|
||||
return Function.bind.call(it.only, it);
|
||||
}
|
||||
|
||||
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."
|
||||
);
|
||||
}
|
||||
if (typeof it === "function") {
|
||||
throw new Error("The current test framework does not support exclusive tests with `only`.");
|
||||
}
|
||||
throw new Error("To use `only`, use RuleTester with a test framework that provides `it.only()` like Mocha.");
|
||||
}
|
||||
|
||||
static set itOnly(value) {
|
||||
this[IT_ONLY] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a rule for one particular run of tests.
|
||||
* @param {string} name The name of the rule to define.
|
||||
|
|
@ -427,12 +477,12 @@ class RuleTester {
|
|||
scenarioErrors = [],
|
||||
linter = this.linter;
|
||||
|
||||
if (lodash.isNil(test) || typeof test !== "object") {
|
||||
if (!test || typeof test !== "object") {
|
||||
throw new TypeError(`Test Scenarios for rule ${ruleName} : Could not find test scenario object`);
|
||||
}
|
||||
|
||||
requiredScenarios.forEach(scenarioType => {
|
||||
if (lodash.isNil(test[scenarioType])) {
|
||||
if (!test[scenarioType]) {
|
||||
scenarioErrors.push(`Could not find any ${scenarioType} test scenarios`);
|
||||
}
|
||||
});
|
||||
|
|
@ -465,7 +515,7 @@ class RuleTester {
|
|||
* @private
|
||||
*/
|
||||
function runRuleForItem(item) {
|
||||
let config = lodash.cloneDeep(testerConfig),
|
||||
let config = merge({}, testerConfig),
|
||||
code, filename, output, beforeAST, afterAST;
|
||||
|
||||
if (typeof item === "string") {
|
||||
|
|
@ -477,13 +527,17 @@ class RuleTester {
|
|||
* Assumes everything on the item is a config except for the
|
||||
* parameters used by this tester
|
||||
*/
|
||||
const itemConfig = lodash.omit(item, RuleTesterParameters);
|
||||
const itemConfig = { ...item };
|
||||
|
||||
for (const parameter of RuleTesterParameters) {
|
||||
delete itemConfig[parameter];
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the config object from the tester config and this item
|
||||
* specific configurations.
|
||||
*/
|
||||
config = lodash.merge(
|
||||
config = merge(
|
||||
config,
|
||||
itemConfig
|
||||
);
|
||||
|
|
@ -589,7 +643,7 @@ class RuleTester {
|
|||
* @private
|
||||
*/
|
||||
function assertASTDidntChange(beforeAST, afterAST) {
|
||||
if (!lodash.isEqual(beforeAST, afterAST)) {
|
||||
if (!equal(beforeAST, afterAST)) {
|
||||
assert.fail("Rule should not modify AST.");
|
||||
}
|
||||
}
|
||||
|
|
@ -606,7 +660,8 @@ class RuleTester {
|
|||
const messages = result.messages;
|
||||
|
||||
assert.strictEqual(messages.length, 0, util.format("Should have no errors but had %d: %s",
|
||||
messages.length, util.inspect(messages)));
|
||||
messages.length,
|
||||
util.inspect(messages)));
|
||||
|
||||
assertASTDidntChange(result.beforeAST, result.afterAST);
|
||||
}
|
||||
|
|
@ -661,13 +716,18 @@ class RuleTester {
|
|||
}
|
||||
|
||||
assert.strictEqual(messages.length, item.errors, util.format("Should have %d error%s but had %d: %s",
|
||||
item.errors, item.errors === 1 ? "" : "s", messages.length, util.inspect(messages)));
|
||||
item.errors,
|
||||
item.errors === 1 ? "" : "s",
|
||||
messages.length,
|
||||
util.inspect(messages)));
|
||||
} else {
|
||||
assert.strictEqual(
|
||||
messages.length, item.errors.length,
|
||||
util.format(
|
||||
messages.length, item.errors.length, util.format(
|
||||
"Should have %d error%s but had %d: %s",
|
||||
item.errors.length, item.errors.length === 1 ? "" : "s", messages.length, util.inspect(messages)
|
||||
item.errors.length,
|
||||
item.errors.length === 1 ? "" : "s",
|
||||
messages.length,
|
||||
util.inspect(messages)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -881,23 +941,29 @@ class RuleTester {
|
|||
RuleTester.describe(ruleName, () => {
|
||||
RuleTester.describe("valid", () => {
|
||||
test.valid.forEach(valid => {
|
||||
RuleTester.it(sanitize(typeof valid === "object" ? valid.code : valid), () => {
|
||||
testValidTemplate(valid);
|
||||
});
|
||||
RuleTester[valid.only ? "itOnly" : "it"](
|
||||
sanitize(typeof valid === "object" ? valid.code : valid),
|
||||
() => {
|
||||
testValidTemplate(valid);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
RuleTester.describe("invalid", () => {
|
||||
test.invalid.forEach(invalid => {
|
||||
RuleTester.it(sanitize(invalid.code), () => {
|
||||
testInvalidTemplate(invalid);
|
||||
});
|
||||
RuleTester[invalid.only ? "itOnly" : "it"](
|
||||
sanitize(invalid.code),
|
||||
() => {
|
||||
testInvalidTemplate(invalid);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
RuleTester[DESCRIBE] = RuleTester[IT] = null;
|
||||
RuleTester[DESCRIBE] = RuleTester[IT] = RuleTester[IT_ONLY] = null;
|
||||
|
||||
module.exports = RuleTester;
|
||||
|
|
|
|||
34
node_modules/eslint/lib/rules/arrow-body-style.js
generated
vendored
34
node_modules/eslint/lib/rules/arrow-body-style.js
generated
vendored
|
|
@ -87,17 +87,17 @@ module.exports = {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the closing parenthesis which is the pair of the given opening parenthesis.
|
||||
* @param {Token} token The opening parenthesis token to get.
|
||||
* Gets the closing parenthesis by the given node.
|
||||
* @param {ASTNode} node first node after an opening parenthesis.
|
||||
* @returns {Token} The found closing parenthesis token.
|
||||
*/
|
||||
function findClosingParen(token) {
|
||||
let node = sourceCode.getNodeByRangeIndex(token.range[0]);
|
||||
function findClosingParen(node) {
|
||||
let nodeToCheck = node;
|
||||
|
||||
while (!astUtils.isParenthesised(sourceCode, node)) {
|
||||
node = node.parent;
|
||||
while (!astUtils.isParenthesised(sourceCode, nodeToCheck)) {
|
||||
nodeToCheck = nodeToCheck.parent;
|
||||
}
|
||||
return sourceCode.getTokenAfter(node);
|
||||
return sourceCode.getTokenAfter(nodeToCheck);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -191,7 +191,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
/*
|
||||
* If the first token of the reutrn value is `{` or the return value is a sequence expression,
|
||||
* If the first token of the return value is `{` or the return value is a sequence expression,
|
||||
* enclose the return value by parentheses to avoid syntax error.
|
||||
*/
|
||||
if (astUtils.isOpeningBraceToken(firstValueToken) || blockBody[0].argument.type === "SequenceExpression" || (funcInfo.hasInOperator && isInsideForLoopInitializer(node))) {
|
||||
|
|
@ -226,12 +226,22 @@ module.exports = {
|
|||
const arrowToken = sourceCode.getTokenBefore(arrowBody, astUtils.isArrowToken);
|
||||
const [firstTokenAfterArrow, secondTokenAfterArrow] = sourceCode.getTokensAfter(arrowToken, { count: 2 });
|
||||
const lastToken = sourceCode.getLastToken(node);
|
||||
const isParenthesisedObjectLiteral =
|
||||
|
||||
let parenthesisedObjectLiteral = null;
|
||||
|
||||
if (
|
||||
astUtils.isOpeningParenToken(firstTokenAfterArrow) &&
|
||||
astUtils.isOpeningBraceToken(secondTokenAfterArrow);
|
||||
astUtils.isOpeningBraceToken(secondTokenAfterArrow)
|
||||
) {
|
||||
const braceNode = sourceCode.getNodeByRangeIndex(secondTokenAfterArrow.range[0]);
|
||||
|
||||
if (braceNode.type === "ObjectExpression") {
|
||||
parenthesisedObjectLiteral = braceNode;
|
||||
}
|
||||
}
|
||||
|
||||
// If the value is object literal, remove parentheses which were forced by syntax.
|
||||
if (isParenthesisedObjectLiteral) {
|
||||
if (parenthesisedObjectLiteral) {
|
||||
const openingParenToken = firstTokenAfterArrow;
|
||||
const openingBraceToken = secondTokenAfterArrow;
|
||||
|
||||
|
|
@ -247,7 +257,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
// Closing paren for the object doesn't have to be lastToken, e.g.: () => ({}).foo()
|
||||
fixes.push(fixer.remove(findClosingParen(openingBraceToken)));
|
||||
fixes.push(fixer.remove(findClosingParen(parenthesisedObjectLiteral)));
|
||||
fixes.push(fixer.insertTextAfter(lastToken, "}"));
|
||||
|
||||
} else {
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/callback-return.js
generated
vendored
4
node_modules/eslint/lib/rules/callback-return.js
generated
vendored
|
|
@ -59,9 +59,9 @@ module.exports = {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check to see if a node contains only identifers
|
||||
* Check to see if a node contains only identifiers
|
||||
* @param {ASTNode} node The node to check
|
||||
* @returns {boolean} Whether or not the node contains only identifers
|
||||
* @returns {boolean} Whether or not the node contains only identifiers
|
||||
*/
|
||||
function containsOnlyIdentifiers(node) {
|
||||
if (node.type === "Identifier") {
|
||||
|
|
|
|||
23
node_modules/eslint/lib/rules/comma-dangle.js
generated
vendored
23
node_modules/eslint/lib/rules/comma-dangle.js
generated
vendored
|
|
@ -9,7 +9,6 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -144,23 +143,33 @@ module.exports = {
|
|||
* @returns {ASTNode|null} The last node or null.
|
||||
*/
|
||||
function getLastItem(node) {
|
||||
|
||||
/**
|
||||
* Returns the last element of an array
|
||||
* @param {any[]} array The input array
|
||||
* @returns {any} The last element
|
||||
*/
|
||||
function last(array) {
|
||||
return array[array.length - 1];
|
||||
}
|
||||
|
||||
switch (node.type) {
|
||||
case "ObjectExpression":
|
||||
case "ObjectPattern":
|
||||
return lodash.last(node.properties);
|
||||
return last(node.properties);
|
||||
case "ArrayExpression":
|
||||
case "ArrayPattern":
|
||||
return lodash.last(node.elements);
|
||||
return last(node.elements);
|
||||
case "ImportDeclaration":
|
||||
case "ExportNamedDeclaration":
|
||||
return lodash.last(node.specifiers);
|
||||
return last(node.specifiers);
|
||||
case "FunctionDeclaration":
|
||||
case "FunctionExpression":
|
||||
case "ArrowFunctionExpression":
|
||||
return lodash.last(node.params);
|
||||
return last(node.params);
|
||||
case "CallExpression":
|
||||
case "NewExpression":
|
||||
return lodash.last(node.arguments);
|
||||
return last(node.arguments);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
@ -316,7 +325,7 @@ module.exports = {
|
|||
"always-multiline": forceTrailingCommaIfMultiline,
|
||||
"only-multiline": allowTrailingCommaIfMultiline,
|
||||
never: forbidTrailingComma,
|
||||
ignore: lodash.noop
|
||||
ignore: () => {}
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/comma-spacing.js
generated
vendored
2
node_modules/eslint/lib/rules/comma-spacing.js
generated
vendored
|
|
@ -181,7 +181,7 @@ module.exports = {
|
|||
|
||||
validateCommaItemSpacing({
|
||||
comma: token,
|
||||
left: astUtils.isCommaToken(previousToken) || commaTokensToIgnore.indexOf(token) > -1 ? null : previousToken,
|
||||
left: astUtils.isCommaToken(previousToken) || commaTokensToIgnore.includes(token) ? null : previousToken,
|
||||
right: astUtils.isCommaToken(nextToken) ? null : nextToken
|
||||
}, token);
|
||||
});
|
||||
|
|
|
|||
3
node_modules/eslint/lib/rules/comma-style.js
generated
vendored
3
node_modules/eslint/lib/rules/comma-style.js
generated
vendored
|
|
@ -207,8 +207,7 @@ module.exports = {
|
|||
* they are always valid regardless of an undefined item.
|
||||
*/
|
||||
if (astUtils.isCommaToken(commaToken)) {
|
||||
validateCommaItemSpacing(previousItemToken, commaToken,
|
||||
currentItemToken, reportItem);
|
||||
validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem);
|
||||
}
|
||||
|
||||
if (item) {
|
||||
|
|
|
|||
13
node_modules/eslint/lib/rules/complexity.js
generated
vendored
13
node_modules/eslint/lib/rules/complexity.js
generated
vendored
|
|
@ -10,9 +10,8 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
const { upperCaseFirst } = require("../shared/string-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
|
|
@ -95,7 +94,7 @@ module.exports = {
|
|||
* @private
|
||||
*/
|
||||
function endFunction(node) {
|
||||
const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(node));
|
||||
const name = upperCaseFirst(astUtils.getFunctionNameWithKind(node));
|
||||
const complexity = fns.pop();
|
||||
|
||||
if (complexity > THRESHOLD) {
|
||||
|
|
@ -153,7 +152,13 @@ module.exports = {
|
|||
IfStatement: increaseComplexity,
|
||||
SwitchCase: increaseSwitchComplexity,
|
||||
WhileStatement: increaseComplexity,
|
||||
DoWhileStatement: increaseComplexity
|
||||
DoWhileStatement: increaseComplexity,
|
||||
|
||||
AssignmentExpression(node) {
|
||||
if (astUtils.isLogicalAssignmentOperator(node.operator)) {
|
||||
increaseComplexity();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
10
node_modules/eslint/lib/rules/consistent-return.js
generated
vendored
10
node_modules/eslint/lib/rules/consistent-return.js
generated
vendored
|
|
@ -8,8 +8,8 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
const { upperCaseFirst } = require("../shared/string-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
|
@ -104,18 +104,18 @@ module.exports = {
|
|||
} else if (node.type === "ArrowFunctionExpression") {
|
||||
|
||||
// `=>` token
|
||||
loc = context.getSourceCode().getTokenBefore(node.body, astUtils.isArrowToken).loc.start;
|
||||
loc = context.getSourceCode().getTokenBefore(node.body, astUtils.isArrowToken).loc;
|
||||
} else if (
|
||||
node.parent.type === "MethodDefinition" ||
|
||||
(node.parent.type === "Property" && node.parent.method)
|
||||
) {
|
||||
|
||||
// Method name.
|
||||
loc = node.parent.key.loc.start;
|
||||
loc = node.parent.key.loc;
|
||||
} else {
|
||||
|
||||
// Function name or `function` keyword.
|
||||
loc = (node.id || node).loc.start;
|
||||
loc = (node.id || context.getSourceCode().getFirstToken(node)).loc;
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
|
|
@ -164,7 +164,7 @@ module.exports = {
|
|||
funcInfo.data = {
|
||||
name: funcInfo.node.type === "Program"
|
||||
? "Program"
|
||||
: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node))
|
||||
: upperCaseFirst(astUtils.getFunctionNameWithKind(funcInfo.node))
|
||||
};
|
||||
} else if (funcInfo.hasReturnValue !== hasReturnValue) {
|
||||
context.report({
|
||||
|
|
|
|||
11
node_modules/eslint/lib/rules/constructor-super.js
generated
vendored
11
node_modules/eslint/lib/rules/constructor-super.js
generated
vendored
|
|
@ -79,6 +79,17 @@ function isPossibleConstructor(node) {
|
|||
return false;
|
||||
|
||||
case "LogicalExpression":
|
||||
|
||||
/*
|
||||
* If the && operator short-circuits, the left side was falsy and therefore not a constructor, and if
|
||||
* it doesn't short-circuit, it takes the value from the right side, so the right side must always be a
|
||||
* possible constructor. A future improvement could verify that the left side could be truthy by
|
||||
* excluding falsy literals.
|
||||
*/
|
||||
if (node.operator === "&&") {
|
||||
return isPossibleConstructor(node.right);
|
||||
}
|
||||
|
||||
return (
|
||||
isPossibleConstructor(node.left) ||
|
||||
isPossibleConstructor(node.right)
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/dot-location.js
generated
vendored
2
node_modules/eslint/lib/rules/dot-location.js
generated
vendored
|
|
@ -46,7 +46,7 @@ module.exports = {
|
|||
const sourceCode = context.getSourceCode();
|
||||
|
||||
/**
|
||||
* Reports if the dot between object and property is on the correct loccation.
|
||||
* Reports if the dot between object and property is on the correct location.
|
||||
* @param {ASTNode} node The `MemberExpression` node.
|
||||
* @returns {void}
|
||||
*/
|
||||
|
|
|
|||
6
node_modules/eslint/lib/rules/dot-notation.js
generated
vendored
6
node_modules/eslint/lib/rules/dot-notation.js
generated
vendored
|
|
@ -94,7 +94,7 @@ module.exports = {
|
|||
|
||||
// Don't perform any fixes if there are comments inside the brackets.
|
||||
if (sourceCode.commentsExistBetween(leftBracket, rightBracket)) {
|
||||
return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace the brackets by an identifier.
|
||||
|
|
@ -154,12 +154,12 @@ module.exports = {
|
|||
|
||||
// A statement that starts with `let[` is parsed as a destructuring variable declaration, not a MemberExpression.
|
||||
if (node.object.type === "Identifier" && node.object.name === "let" && !node.optional) {
|
||||
return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't perform any fixes if there are comments between the dot and the property name.
|
||||
if (sourceCode.commentsExistBetween(dotToken, node.property)) {
|
||||
return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace the identifier to brackets.
|
||||
|
|
|
|||
11
node_modules/eslint/lib/rules/eol-last.js
generated
vendored
11
node_modules/eslint/lib/rules/eol-last.js
generated
vendored
|
|
@ -4,12 +4,6 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -48,13 +42,14 @@ module.exports = {
|
|||
Program: function checkBadEOF(node) {
|
||||
const sourceCode = context.getSourceCode(),
|
||||
src = sourceCode.getText(),
|
||||
lastLine = sourceCode.lines[sourceCode.lines.length - 1],
|
||||
location = {
|
||||
column: lodash.last(sourceCode.lines).length,
|
||||
column: lastLine.length,
|
||||
line: sourceCode.lines.length
|
||||
},
|
||||
LF = "\n",
|
||||
CRLF = `\r${LF}`,
|
||||
endsWithNewline = lodash.endsWith(src, LF);
|
||||
endsWithNewline = src.endsWith(LF);
|
||||
|
||||
/*
|
||||
* Empty source is always valid: No content in file so we don't
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/func-call-spacing.js
generated
vendored
4
node_modules/eslint/lib/rules/func-call-spacing.js
generated
vendored
|
|
@ -131,7 +131,7 @@ module.exports = {
|
|||
return null;
|
||||
}
|
||||
|
||||
// If `?.` exsits, it doesn't hide no-undexpected-multiline errors
|
||||
// If `?.` exists, it doesn't hide no-unexpected-multiline errors
|
||||
if (node.optional) {
|
||||
return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], "?.");
|
||||
}
|
||||
|
|
@ -177,7 +177,7 @@ module.exports = {
|
|||
/*
|
||||
* Only autofix if there is no newline
|
||||
* https://github.com/eslint/eslint/issues/7787
|
||||
* But if `?.` exsits, it doesn't hide no-undexpected-multiline errors
|
||||
* But if `?.` exists, it doesn't hide no-unexpected-multiline errors
|
||||
*/
|
||||
if (!node.optional) {
|
||||
return null;
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/function-paren-newline.js
generated
vendored
2
node_modules/eslint/lib/rules/function-paren-newline.js
generated
vendored
|
|
@ -218,7 +218,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
case "ArrowFunctionExpression": {
|
||||
const firstToken = sourceCode.getFirstToken(node);
|
||||
const firstToken = sourceCode.getFirstToken(node, { skip: (node.async ? 1 : 0) });
|
||||
|
||||
if (!astUtils.isOpeningParenToken(firstToken)) {
|
||||
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/indent-legacy.js
generated
vendored
2
node_modules/eslint/lib/rules/indent-legacy.js
generated
vendored
|
|
@ -954,7 +954,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks wether a return statement is wrapped in ()
|
||||
* Checks whether a return statement is wrapped in ()
|
||||
* @param {ASTNode} node node to examine
|
||||
* @returns {boolean} the result
|
||||
*/
|
||||
|
|
|
|||
22
node_modules/eslint/lib/rules/indent.js
generated
vendored
22
node_modules/eslint/lib/rules/indent.js
generated
vendored
|
|
@ -12,10 +12,10 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
const createTree = require("functional-red-black-tree");
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -1068,7 +1068,7 @@ module.exports = {
|
|||
const baseOffsetListeners = {
|
||||
"ArrayExpression, ArrayPattern"(node) {
|
||||
const openingBracket = sourceCode.getFirstToken(node);
|
||||
const closingBracket = sourceCode.getTokenAfter(lodash.findLast(node.elements) || openingBracket, astUtils.isClosingBracketToken);
|
||||
const closingBracket = sourceCode.getTokenAfter([...node.elements].reverse().find(_ => _) || openingBracket, astUtils.isClosingBracketToken);
|
||||
|
||||
addElementListIndent(node.elements, openingBracket, closingBracket, options.ArrayExpression);
|
||||
},
|
||||
|
|
@ -1177,7 +1177,7 @@ module.exports = {
|
|||
offsets.setDesiredOffset(questionMarkToken, firstToken, 1);
|
||||
offsets.setDesiredOffset(colonToken, firstToken, 1);
|
||||
|
||||
offsets.setDesiredOffset(firstConsequentToken, firstToken,
|
||||
offsets.setDesiredOffset(firstConsequentToken, firstToken, firstConsequentToken.type === "Punctuator" &&
|
||||
options.offsetTernaryExpressions ? 2 : 1);
|
||||
|
||||
/*
|
||||
|
|
@ -1203,8 +1203,7 @@ module.exports = {
|
|||
* If `baz` were aligned with `bar` rather than being offset by 1 from `foo`, `baz` would end up
|
||||
* having no expected indentation.
|
||||
*/
|
||||
offsets.setDesiredOffset(firstAlternateToken, firstToken,
|
||||
firstAlternateToken.type === "Punctuator" &&
|
||||
offsets.setDesiredOffset(firstAlternateToken, firstToken, firstAlternateToken.type === "Punctuator" &&
|
||||
options.offsetTernaryExpressions ? 2 : 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -1559,8 +1558,9 @@ module.exports = {
|
|||
* 2. Don't set any offsets against the first token of the node.
|
||||
* 3. Call `ignoreNode` on the node sometime after exiting it and before validating offsets.
|
||||
*/
|
||||
const offsetListeners = lodash.mapValues(
|
||||
baseOffsetListeners,
|
||||
const offsetListeners = {};
|
||||
|
||||
for (const [selector, listener] of Object.entries(baseOffsetListeners)) {
|
||||
|
||||
/*
|
||||
* Offset listener calls are deferred until traversal is finished, and are called as
|
||||
|
|
@ -1578,10 +1578,8 @@ module.exports = {
|
|||
* To avoid this, the `Identifier` listener isn't called until traversal finishes and all
|
||||
* ignored nodes are known.
|
||||
*/
|
||||
listener =>
|
||||
node =>
|
||||
listenerCallQueue.push({ listener, node })
|
||||
);
|
||||
offsetListeners[selector] = node => listenerCallQueue.push({ listener, node });
|
||||
}
|
||||
|
||||
// For each ignored node selector, set up a listener to collect it into the `ignoredNodes` set.
|
||||
const ignoredNodes = new Set();
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/index.js
generated
vendored
2
node_modules/eslint/lib/rules/index.js
generated
vendored
|
|
@ -169,6 +169,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|||
"no-new-require": () => require("./no-new-require"),
|
||||
"no-new-symbol": () => require("./no-new-symbol"),
|
||||
"no-new-wrappers": () => require("./no-new-wrappers"),
|
||||
"no-nonoctal-decimal-escape": () => require("./no-nonoctal-decimal-escape"),
|
||||
"no-obj-calls": () => require("./no-obj-calls"),
|
||||
"no-octal": () => require("./no-octal"),
|
||||
"no-octal-escape": () => require("./no-octal-escape"),
|
||||
|
|
@ -217,6 +218,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|||
"no-unreachable-loop": () => require("./no-unreachable-loop"),
|
||||
"no-unsafe-finally": () => require("./no-unsafe-finally"),
|
||||
"no-unsafe-negation": () => require("./no-unsafe-negation"),
|
||||
"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-vars": () => require("./no-unused-vars"),
|
||||
|
|
|
|||
7
node_modules/eslint/lib/rules/lines-around-comment.js
generated
vendored
7
node_modules/eslint/lib/rules/lines-around-comment.js
generated
vendored
|
|
@ -8,8 +8,7 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash"),
|
||||
astUtils = require("./utils/ast-utils");
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
|
@ -347,7 +346,7 @@ module.exports = {
|
|||
const nextTokenOrComment = sourceCode.getTokenAfter(token, { includeComments: true });
|
||||
|
||||
// check for newline before
|
||||
if (!exceptionStartAllowed && before && !lodash.includes(commentAndEmptyLines, prevLineNum) &&
|
||||
if (!exceptionStartAllowed && before && !commentAndEmptyLines.includes(prevLineNum) &&
|
||||
!(astUtils.isCommentToken(previousTokenOrComment) && astUtils.isTokenOnSameLine(previousTokenOrComment, token))) {
|
||||
const lineStart = token.range[0] - token.loc.start.column;
|
||||
const range = [lineStart, lineStart];
|
||||
|
|
@ -362,7 +361,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
// check for newline after
|
||||
if (!exceptionEndAllowed && after && !lodash.includes(commentAndEmptyLines, nextLineNum) &&
|
||||
if (!exceptionEndAllowed && after && !commentAndEmptyLines.includes(nextLineNum) &&
|
||||
!(astUtils.isCommentToken(nextTokenOrComment) && astUtils.isTokenOnSameLine(token, nextTokenOrComment))) {
|
||||
context.report({
|
||||
node: token,
|
||||
|
|
|
|||
7
node_modules/eslint/lib/rules/max-lines-per-function.js
generated
vendored
7
node_modules/eslint/lib/rules/max-lines-per-function.js
generated
vendored
|
|
@ -9,8 +9,7 @@
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
const lodash = require("lodash");
|
||||
const { upperCaseFirst } = require("../shared/string-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Constants
|
||||
|
|
@ -71,7 +70,7 @@ module.exports = {
|
|||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "enforce a maximum number of line of code in a function",
|
||||
description: "enforce a maximum number of lines of code in a function",
|
||||
category: "Stylistic Issues",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/max-lines-per-function"
|
||||
|
|
@ -191,7 +190,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
if (lineCount > maxLines) {
|
||||
const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(funcNode));
|
||||
const name = upperCaseFirst(astUtils.getFunctionNameWithKind(funcNode));
|
||||
|
||||
context.report({
|
||||
node,
|
||||
|
|
|
|||
47
node_modules/eslint/lib/rules/max-lines.js
generated
vendored
47
node_modules/eslint/lib/rules/max-lines.js
generated
vendored
|
|
@ -8,9 +8,22 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates an array of numbers from `start` up to, but not including, `end`
|
||||
* @param {number} start The start of the range
|
||||
* @param {number} end The end of the range
|
||||
* @returns {number[]} The range of numbers
|
||||
*/
|
||||
function range(start, end) {
|
||||
return [...Array(end - start).keys()].map(x => x + start);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -119,11 +132,25 @@ module.exports = {
|
|||
}
|
||||
|
||||
if (start <= end) {
|
||||
return lodash.range(start, end + 1);
|
||||
return range(start, end + 1);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
return {
|
||||
"Program:exit"() {
|
||||
let lines = sourceCode.lines.map((text, i) => ({
|
||||
|
|
@ -131,6 +158,14 @@ module.exports = {
|
|||
text
|
||||
}));
|
||||
|
||||
/*
|
||||
* If file ends with a linebreak, `sourceCode.lines` will have one extra empty line at the end.
|
||||
* That isn't a real line, so we shouldn't count it.
|
||||
*/
|
||||
if (lines.length > 1 && lines[lines.length - 1].text === "") {
|
||||
lines.pop();
|
||||
}
|
||||
|
||||
if (skipBlankLines) {
|
||||
lines = lines.filter(l => l.text.trim() !== "");
|
||||
}
|
||||
|
|
@ -138,12 +173,10 @@ module.exports = {
|
|||
if (skipComments) {
|
||||
const comments = sourceCode.getAllComments();
|
||||
|
||||
const commentLines = lodash.flatten(
|
||||
comments.map(comment => getLinesWithoutCode(comment))
|
||||
);
|
||||
const commentLines = flatMap(comments, comment => getLinesWithoutCode(comment));
|
||||
|
||||
lines = lines.filter(
|
||||
l => !lodash.includes(commentLines, l.lineNumber)
|
||||
l => !commentLines.includes(l.lineNumber)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +188,7 @@ module.exports = {
|
|||
},
|
||||
end: {
|
||||
line: sourceCode.lines.length,
|
||||
column: lodash.last(sourceCode.lines).length
|
||||
column: sourceCode.lines[sourceCode.lines.length - 1].length
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
5
node_modules/eslint/lib/rules/max-params.js
generated
vendored
5
node_modules/eslint/lib/rules/max-params.js
generated
vendored
|
|
@ -9,9 +9,8 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
const { upperCaseFirst } = require("../shared/string-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
|
|
@ -85,7 +84,7 @@ module.exports = {
|
|||
node,
|
||||
messageId: "exceed",
|
||||
data: {
|
||||
name: lodash.upperFirst(astUtils.getFunctionNameWithKind(node)),
|
||||
name: upperCaseFirst(astUtils.getFunctionNameWithKind(node)),
|
||||
count: node.params.length,
|
||||
max: numParams
|
||||
}
|
||||
|
|
|
|||
5
node_modules/eslint/lib/rules/max-statements.js
generated
vendored
5
node_modules/eslint/lib/rules/max-statements.js
generated
vendored
|
|
@ -9,9 +9,8 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
const { upperCaseFirst } = require("../shared/string-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
|
|
@ -97,7 +96,7 @@ module.exports = {
|
|||
*/
|
||||
function reportIfTooManyStatements(node, count, max) {
|
||||
if (count > max) {
|
||||
const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(node));
|
||||
const name = upperCaseFirst(astUtils.getFunctionNameWithKind(node));
|
||||
|
||||
context.report({
|
||||
node,
|
||||
|
|
|
|||
69
node_modules/eslint/lib/rules/multiline-ternary.js
generated
vendored
69
node_modules/eslint/lib/rules/multiline-ternary.js
generated
vendored
|
|
@ -27,19 +27,22 @@ module.exports = {
|
|||
enum: ["always", "always-multiline", "never"]
|
||||
}
|
||||
],
|
||||
|
||||
messages: {
|
||||
expectedTestCons: "Expected newline between test and consequent of ternary expression.",
|
||||
expectedConsAlt: "Expected newline between consequent and alternate of ternary expression.",
|
||||
unexpectedTestCons: "Unexpected newline between test and consequent of ternary expression.",
|
||||
unexpectedConsAlt: "Unexpected newline between consequent and alternate of ternary expression."
|
||||
}
|
||||
},
|
||||
|
||||
fixable: "whitespace"
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
const option = context.options[0];
|
||||
const multiline = option !== "never";
|
||||
const allowSingleLine = option === "always-multiline";
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
|
|
@ -59,6 +62,8 @@ module.exports = {
|
|||
const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, firstTokenOfConsequent);
|
||||
const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, firstTokenOfAlternate);
|
||||
|
||||
const hasComments = !!sourceCode.getCommentsInside(node).length;
|
||||
|
||||
if (!multiline) {
|
||||
if (!areTestAndConsequentOnSameLine) {
|
||||
context.report({
|
||||
|
|
@ -67,7 +72,24 @@ module.exports = {
|
|||
start: firstTokenOfTest.loc.start,
|
||||
end: lastTokenOfTest.loc.end
|
||||
},
|
||||
messageId: "unexpectedTestCons"
|
||||
messageId: "unexpectedTestCons",
|
||||
fix: fixer => {
|
||||
if (hasComments) {
|
||||
return null;
|
||||
}
|
||||
const fixers = [];
|
||||
const areTestAndQuestionOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, questionToken);
|
||||
const areQuestionAndConsOnSameLine = astUtils.isTokenOnSameLine(questionToken, firstTokenOfConsequent);
|
||||
|
||||
if (!areTestAndQuestionOnSameLine) {
|
||||
fixers.push(fixer.removeRange([lastTokenOfTest.range[1], questionToken.range[0]]));
|
||||
}
|
||||
if (!areQuestionAndConsOnSameLine) {
|
||||
fixers.push(fixer.removeRange([questionToken.range[1], firstTokenOfConsequent.range[0]]));
|
||||
}
|
||||
|
||||
return fixers;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +100,24 @@ module.exports = {
|
|||
start: firstTokenOfConsequent.loc.start,
|
||||
end: lastTokenOfConsequent.loc.end
|
||||
},
|
||||
messageId: "unexpectedConsAlt"
|
||||
messageId: "unexpectedConsAlt",
|
||||
fix: fixer => {
|
||||
if (hasComments) {
|
||||
return null;
|
||||
}
|
||||
const fixers = [];
|
||||
const areConsAndColonOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, colonToken);
|
||||
const areColonAndAltOnSameLine = astUtils.isTokenOnSameLine(colonToken, firstTokenOfAlternate);
|
||||
|
||||
if (!areConsAndColonOnSameLine) {
|
||||
fixers.push(fixer.removeRange([lastTokenOfConsequent.range[1], colonToken.range[0]]));
|
||||
}
|
||||
if (!areColonAndAltOnSameLine) {
|
||||
fixers.push(fixer.removeRange([colonToken.range[1], firstTokenOfAlternate.range[0]]));
|
||||
}
|
||||
|
||||
return fixers;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
@ -93,7 +132,16 @@ module.exports = {
|
|||
start: firstTokenOfTest.loc.start,
|
||||
end: lastTokenOfTest.loc.end
|
||||
},
|
||||
messageId: "expectedTestCons"
|
||||
messageId: "expectedTestCons",
|
||||
fix: fixer => (hasComments ? null : (
|
||||
fixer.replaceTextRange(
|
||||
[
|
||||
lastTokenOfTest.range[1],
|
||||
questionToken.range[0]
|
||||
],
|
||||
"\n"
|
||||
)
|
||||
))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +152,16 @@ module.exports = {
|
|||
start: firstTokenOfConsequent.loc.start,
|
||||
end: lastTokenOfConsequent.loc.end
|
||||
},
|
||||
messageId: "expectedConsAlt"
|
||||
messageId: "expectedConsAlt",
|
||||
fix: (fixer => (hasComments ? null : (
|
||||
fixer.replaceTextRange(
|
||||
[
|
||||
lastTokenOfConsequent.range[1],
|
||||
colonToken.range[0]
|
||||
],
|
||||
"\n"
|
||||
)
|
||||
)))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
89
node_modules/eslint/lib/rules/no-constant-condition.js
generated
vendored
89
node_modules/eslint/lib/rules/no-constant-condition.js
generated
vendored
|
|
@ -9,9 +9,6 @@
|
|||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const EQUALITY_OPERATORS = ["===", "!==", "==", "!="];
|
||||
const RELATIONAL_OPERATORS = [">", "<", ">=", "<=", "in", "instanceof"];
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -56,6 +53,35 @@ module.exports = {
|
|||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns literal's value converted to the Boolean type
|
||||
* @param {ASTNode} node any `Literal` node
|
||||
* @returns {boolean | null} `true` when node is truthy, `false` when node is falsy,
|
||||
* `null` when it cannot be determined.
|
||||
*/
|
||||
function getBooleanValue(node) {
|
||||
if (node.value === null) {
|
||||
|
||||
/*
|
||||
* it might be a null literal or bigint/regex literal in unsupported environments .
|
||||
* https://github.com/estree/estree/blob/14df8a024956ea289bd55b9c2226a1d5b8a473ee/es5.md#regexpliteral
|
||||
* https://github.com/estree/estree/blob/14df8a024956ea289bd55b9c2226a1d5b8a473ee/es2020.md#bigintliteral
|
||||
*/
|
||||
|
||||
if (node.raw === "null") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// regex is always truthy
|
||||
if (typeof node.regex === "object") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return !!node.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a branch node of LogicalExpression short circuits the whole condition
|
||||
|
|
@ -66,15 +92,28 @@ module.exports = {
|
|||
function isLogicalIdentity(node, operator) {
|
||||
switch (node.type) {
|
||||
case "Literal":
|
||||
return (operator === "||" && node.value === true) ||
|
||||
(operator === "&&" && node.value === false);
|
||||
return (operator === "||" && getBooleanValue(node) === true) ||
|
||||
(operator === "&&" && getBooleanValue(node) === false);
|
||||
|
||||
case "UnaryExpression":
|
||||
return (operator === "&&" && node.operator === "void");
|
||||
|
||||
case "LogicalExpression":
|
||||
return isLogicalIdentity(node.left, node.operator) ||
|
||||
isLogicalIdentity(node.right, node.operator);
|
||||
|
||||
/*
|
||||
* handles `a && false || b`
|
||||
* `false` is an identity element of `&&` but not `||`
|
||||
*/
|
||||
return operator === node.operator &&
|
||||
(
|
||||
isLogicalIdentity(node.left, operator) ||
|
||||
isLogicalIdentity(node.right, operator)
|
||||
);
|
||||
|
||||
case "AssignmentExpression":
|
||||
return ["||=", "&&="].includes(node.operator) &&
|
||||
operator === node.operator.slice(0, -1) &&
|
||||
isLogicalIdentity(node.right, operator);
|
||||
|
||||
// no default
|
||||
}
|
||||
|
|
@ -113,12 +152,18 @@ module.exports = {
|
|||
}
|
||||
|
||||
case "UnaryExpression":
|
||||
if (node.operator === "void") {
|
||||
if (
|
||||
node.operator === "void" ||
|
||||
node.operator === "typeof" && inBooleanPosition
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (node.operator === "typeof" && inBooleanPosition) ||
|
||||
isConstant(node.argument, true);
|
||||
if (node.operator === "!") {
|
||||
return isConstant(node.argument, true);
|
||||
}
|
||||
|
||||
return isConstant(node.argument, false);
|
||||
|
||||
case "BinaryExpression":
|
||||
return isConstant(node.left, false) &&
|
||||
|
|
@ -129,27 +174,23 @@ module.exports = {
|
|||
const isLeftConstant = isConstant(node.left, inBooleanPosition);
|
||||
const isRightConstant = isConstant(node.right, inBooleanPosition);
|
||||
const isLeftShortCircuit = (isLeftConstant && isLogicalIdentity(node.left, node.operator));
|
||||
const isRightShortCircuit = (isRightConstant && isLogicalIdentity(node.right, node.operator));
|
||||
const isRightShortCircuit = (inBooleanPosition && isRightConstant && isLogicalIdentity(node.right, node.operator));
|
||||
|
||||
return (isLeftConstant && isRightConstant) ||
|
||||
(
|
||||
|
||||
// in the case of an "OR", we need to know if the right constant value is truthy
|
||||
node.operator === "||" &&
|
||||
isRightConstant &&
|
||||
node.right.value &&
|
||||
(
|
||||
!node.parent ||
|
||||
node.parent.type !== "BinaryExpression" ||
|
||||
!(EQUALITY_OPERATORS.includes(node.parent.operator) || RELATIONAL_OPERATORS.includes(node.parent.operator))
|
||||
)
|
||||
) ||
|
||||
isLeftShortCircuit ||
|
||||
isRightShortCircuit;
|
||||
}
|
||||
|
||||
case "AssignmentExpression":
|
||||
return (node.operator === "=") && isConstant(node.right, inBooleanPosition);
|
||||
if (node.operator === "=") {
|
||||
return isConstant(node.right, inBooleanPosition);
|
||||
}
|
||||
|
||||
if (["||=", "&&="].includes(node.operator) && inBooleanPosition) {
|
||||
return isLogicalIdentity(node.right, node.operator.slice(0, -1));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
case "SequenceExpression":
|
||||
return isConstant(node.expressions[node.expressions.length - 1], inBooleanPosition);
|
||||
|
|
|
|||
1
node_modules/eslint/lib/rules/no-control-regex.js
generated
vendored
1
node_modules/eslint/lib/rules/no-control-regex.js
generated
vendored
|
|
@ -8,7 +8,6 @@
|
|||
const RegExpValidator = require("regexpp").RegExpValidator;
|
||||
const collector = new (class {
|
||||
constructor() {
|
||||
this.ecmaVersion = 2018;
|
||||
this._source = "";
|
||||
this._controlChars = [];
|
||||
this._validator = new RegExpValidator(this);
|
||||
|
|
|
|||
282
node_modules/eslint/lib/rules/no-duplicate-imports.js
generated
vendored
282
node_modules/eslint/lib/rules/no-duplicate-imports.js
generated
vendored
|
|
@ -4,42 +4,183 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const NAMED_TYPES = ["ImportSpecifier", "ExportSpecifier"];
|
||||
const NAMESPACE_TYPES = [
|
||||
"ImportNamespaceSpecifier",
|
||||
"ExportNamespaceSpecifier"
|
||||
];
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check if an import/export type belongs to (ImportSpecifier|ExportSpecifier) or (ImportNamespaceSpecifier|ExportNamespaceSpecifier).
|
||||
* @param {string} importExportType An import/export type to check.
|
||||
* @param {string} type Can be "named" or "namespace"
|
||||
* @returns {boolean} True if import/export type belongs to (ImportSpecifier|ExportSpecifier) or (ImportNamespaceSpecifier|ExportNamespaceSpecifier) and false if it doesn't.
|
||||
*/
|
||||
function isImportExportSpecifier(importExportType, type) {
|
||||
const arrayToCheck = type === "named" ? NAMED_TYPES : NAMESPACE_TYPES;
|
||||
|
||||
return arrayToCheck.includes(importExportType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of (import|export).
|
||||
* @param {ASTNode} node A node to get.
|
||||
* @returns {string} The type of the (import|export).
|
||||
*/
|
||||
function getImportExportType(node) {
|
||||
if (node.specifiers && node.specifiers.length > 0) {
|
||||
const nodeSpecifiers = node.specifiers;
|
||||
const index = nodeSpecifiers.findIndex(
|
||||
({ type }) =>
|
||||
isImportExportSpecifier(type, "named") ||
|
||||
isImportExportSpecifier(type, "namespace")
|
||||
);
|
||||
const i = index > -1 ? index : 0;
|
||||
|
||||
return nodeSpecifiers[i].type;
|
||||
}
|
||||
if (node.type === "ExportAllDeclaration") {
|
||||
if (node.exported) {
|
||||
return "ExportNamespaceSpecifier";
|
||||
}
|
||||
return "ExportAll";
|
||||
}
|
||||
return "SideEffectImport";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean indicates if two (import|export) can be merged
|
||||
* @param {ASTNode} node1 A node to check.
|
||||
* @param {ASTNode} node2 A node to check.
|
||||
* @returns {boolean} True if two (import|export) can be merged, false if they can't.
|
||||
*/
|
||||
function isImportExportCanBeMerged(node1, node2) {
|
||||
const importExportType1 = getImportExportType(node1);
|
||||
const importExportType2 = getImportExportType(node2);
|
||||
|
||||
if (
|
||||
(importExportType1 === "ExportAll" &&
|
||||
importExportType2 !== "ExportAll" &&
|
||||
importExportType2 !== "SideEffectImport") ||
|
||||
(importExportType1 !== "ExportAll" &&
|
||||
importExportType1 !== "SideEffectImport" &&
|
||||
importExportType2 === "ExportAll")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
(isImportExportSpecifier(importExportType1, "namespace") &&
|
||||
isImportExportSpecifier(importExportType2, "named")) ||
|
||||
(isImportExportSpecifier(importExportType2, "namespace") &&
|
||||
isImportExportSpecifier(importExportType1, "named"))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean if we should report (import|export).
|
||||
* @param {ASTNode} node A node to be reported or not.
|
||||
* @param {[ASTNode]} previousNodes An array contains previous nodes of the module imported or exported.
|
||||
* @returns {boolean} True if the (import|export) should be reported.
|
||||
*/
|
||||
function shouldReportImportExport(node, previousNodes) {
|
||||
let i = 0;
|
||||
|
||||
while (i < previousNodes.length) {
|
||||
if (isImportExportCanBeMerged(node, previousNodes[i])) {
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array contains only nodes with declarations types equal to type.
|
||||
* @param {[{node: ASTNode, declarationType: string}]} nodes An array contains objects, each object contains a node and a declaration type.
|
||||
* @param {string} type Declaration type.
|
||||
* @returns {[ASTNode]} An array contains only nodes with declarations types equal to type.
|
||||
*/
|
||||
function getNodesByDeclarationType(nodes, type) {
|
||||
return nodes
|
||||
.filter(({ declarationType }) => declarationType === type)
|
||||
.map(({ node }) => node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the module imported or re-exported.
|
||||
* @param {ASTNode} node A node to get.
|
||||
* @returns {string} the name of the module, or empty string if no name.
|
||||
* @returns {string} The name of the module, or empty string if no name.
|
||||
*/
|
||||
function getValue(node) {
|
||||
function getModule(node) {
|
||||
if (node && node.source && node.source.value) {
|
||||
return node.source.value.trim();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the name of the import or export exists in the given array, and reports if so.
|
||||
* Checks if the (import|export) can be merged with at least one import or one export, and reports if so.
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {ASTNode} node A node to get.
|
||||
* @param {string} value The name of the imported or exported module.
|
||||
* @param {string[]} array The array containing other imports or exports in the file.
|
||||
* @param {string} messageId A messageId to be reported after the name of the module
|
||||
*
|
||||
* @returns {void} No return value
|
||||
* @param {Map} modules A Map object contains as a key a module name and as value an array contains objects, each object contains a node and a declaration type.
|
||||
* @param {string} declarationType A declaration type can be an import or export.
|
||||
* @param {boolean} includeExports Whether or not to check for exports in addition to imports.
|
||||
* @returns {void} No return value.
|
||||
*/
|
||||
function checkAndReport(context, node, value, array, messageId) {
|
||||
if (array.indexOf(value) !== -1) {
|
||||
context.report({
|
||||
node,
|
||||
messageId,
|
||||
data: {
|
||||
module: value
|
||||
function checkAndReport(
|
||||
context,
|
||||
node,
|
||||
modules,
|
||||
declarationType,
|
||||
includeExports
|
||||
) {
|
||||
const module = getModule(node);
|
||||
|
||||
if (modules.has(module)) {
|
||||
const previousNodes = modules.get(module);
|
||||
const messagesIds = [];
|
||||
const importNodes = getNodesByDeclarationType(previousNodes, "import");
|
||||
let exportNodes;
|
||||
|
||||
if (includeExports) {
|
||||
exportNodes = getNodesByDeclarationType(previousNodes, "export");
|
||||
}
|
||||
if (declarationType === "import") {
|
||||
if (shouldReportImportExport(node, importNodes)) {
|
||||
messagesIds.push("import");
|
||||
}
|
||||
});
|
||||
if (includeExports) {
|
||||
if (shouldReportImportExport(node, exportNodes)) {
|
||||
messagesIds.push("importAs");
|
||||
}
|
||||
}
|
||||
} else if (declarationType === "export") {
|
||||
if (shouldReportImportExport(node, exportNodes)) {
|
||||
messagesIds.push("export");
|
||||
}
|
||||
if (shouldReportImportExport(node, importNodes)) {
|
||||
messagesIds.push("exportAs");
|
||||
}
|
||||
}
|
||||
messagesIds.forEach(messageId =>
|
||||
context.report({
|
||||
node,
|
||||
messageId,
|
||||
data: {
|
||||
module
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,47 +190,39 @@ function checkAndReport(context, node, value, array, messageId) {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Returns a function handling the imports of a given file
|
||||
* Returns a function handling the (imports|exports) of a given file
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {Map} modules A Map object contains as a key a module name and as value an array contains objects, each object contains a node and a declaration type.
|
||||
* @param {string} declarationType A declaration type can be an import or export.
|
||||
* @param {boolean} includeExports Whether or not to check for exports in addition to imports.
|
||||
* @param {string[]} importsInFile The array containing other imports in the file.
|
||||
* @param {string[]} exportsInFile The array containing other exports in the file.
|
||||
*
|
||||
* @returns {nodeCallback} A function passed to ESLint to handle the statement.
|
||||
*/
|
||||
function handleImports(context, includeExports, importsInFile, exportsInFile) {
|
||||
function handleImportsExports(
|
||||
context,
|
||||
modules,
|
||||
declarationType,
|
||||
includeExports
|
||||
) {
|
||||
return function(node) {
|
||||
const value = getValue(node);
|
||||
const module = getModule(node);
|
||||
|
||||
if (value) {
|
||||
checkAndReport(context, node, value, importsInFile, "import");
|
||||
if (module) {
|
||||
checkAndReport(
|
||||
context,
|
||||
node,
|
||||
modules,
|
||||
declarationType,
|
||||
includeExports
|
||||
);
|
||||
const currentNode = { node, declarationType };
|
||||
let nodes = [currentNode];
|
||||
|
||||
if (includeExports) {
|
||||
checkAndReport(context, node, value, exportsInFile, "importAs");
|
||||
if (modules.has(module)) {
|
||||
const previousNodes = modules.get(module);
|
||||
|
||||
nodes = [...previousNodes, currentNode];
|
||||
}
|
||||
|
||||
importsInFile.push(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function handling the exports of a given file
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {string[]} importsInFile The array containing other imports in the file.
|
||||
* @param {string[]} exportsInFile The array containing other exports in the file.
|
||||
*
|
||||
* @returns {nodeCallback} A function passed to ESLint to handle the statement.
|
||||
*/
|
||||
function handleExports(context, importsInFile, exportsInFile) {
|
||||
return function(node) {
|
||||
const value = getValue(node);
|
||||
|
||||
if (value) {
|
||||
checkAndReport(context, node, value, exportsInFile, "export");
|
||||
checkAndReport(context, node, value, importsInFile, "exportAs");
|
||||
|
||||
exportsInFile.push(value);
|
||||
modules.set(module, nodes);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -105,16 +238,19 @@ module.exports = {
|
|||
url: "https://eslint.org/docs/rules/no-duplicate-imports"
|
||||
},
|
||||
|
||||
schema: [{
|
||||
type: "object",
|
||||
properties: {
|
||||
includeExports: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}],
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
includeExports: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
],
|
||||
|
||||
messages: {
|
||||
import: "'{{module}}' import is duplicated.",
|
||||
importAs: "'{{module}}' import is duplicated as export.",
|
||||
|
|
@ -125,18 +261,30 @@ module.exports = {
|
|||
|
||||
create(context) {
|
||||
const includeExports = (context.options[0] || {}).includeExports,
|
||||
importsInFile = [],
|
||||
exportsInFile = [];
|
||||
|
||||
modules = new Map();
|
||||
const handlers = {
|
||||
ImportDeclaration: handleImports(context, includeExports, importsInFile, exportsInFile)
|
||||
ImportDeclaration: handleImportsExports(
|
||||
context,
|
||||
modules,
|
||||
"import",
|
||||
includeExports
|
||||
)
|
||||
};
|
||||
|
||||
if (includeExports) {
|
||||
handlers.ExportNamedDeclaration = handleExports(context, importsInFile, exportsInFile);
|
||||
handlers.ExportAllDeclaration = handleExports(context, importsInFile, exportsInFile);
|
||||
handlers.ExportNamedDeclaration = handleImportsExports(
|
||||
context,
|
||||
modules,
|
||||
"export",
|
||||
includeExports
|
||||
);
|
||||
handlers.ExportAllDeclaration = handleImportsExports(
|
||||
context,
|
||||
modules,
|
||||
"export",
|
||||
includeExports
|
||||
);
|
||||
}
|
||||
|
||||
return handlers;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/no-extend-native.js
generated
vendored
2
node_modules/eslint/lib/rules/no-extend-native.js
generated
vendored
|
|
@ -138,7 +138,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
/*
|
||||
* `identifierNode.parent` is a MamberExpression `*.prototype`.
|
||||
* `identifierNode.parent` is a MemberExpression `*.prototype`.
|
||||
* If it's an optional member access, it may be wrapped by a `ChainExpression` node.
|
||||
*/
|
||||
const prototypeNode =
|
||||
|
|
|
|||
119
node_modules/eslint/lib/rules/no-extra-parens.js
generated
vendored
119
node_modules/eslint/lib/rules/no-extra-parens.js
generated
vendored
|
|
@ -472,20 +472,34 @@ module.exports = {
|
|||
const callee = node.callee;
|
||||
|
||||
if (hasExcessParensWithPrecedence(callee, precedence(node))) {
|
||||
const hasNewParensException = callee.type === "NewExpression" && !isNewExpressionWithParens(callee);
|
||||
|
||||
if (
|
||||
hasDoubleExcessParens(callee) ||
|
||||
!isIIFE(node) &&
|
||||
!hasNewParensException &&
|
||||
!(
|
||||
isIIFE(node) ||
|
||||
|
||||
// Allow extra parens around a new expression if they are intervening parentheses.
|
||||
node.type === "NewExpression" &&
|
||||
callee.type === "MemberExpression" &&
|
||||
doesMemberExpressionContainCallExpression(callee)
|
||||
) &&
|
||||
!(!node.optional && callee.type === "ChainExpression")
|
||||
// (new A)(); new (new A)();
|
||||
(
|
||||
callee.type === "NewExpression" &&
|
||||
!isNewExpressionWithParens(callee) &&
|
||||
!(
|
||||
node.type === "NewExpression" &&
|
||||
!isNewExpressionWithParens(node)
|
||||
)
|
||||
) ||
|
||||
|
||||
// new (a().b)(); new (a.b().c);
|
||||
(
|
||||
node.type === "NewExpression" &&
|
||||
callee.type === "MemberExpression" &&
|
||||
doesMemberExpressionContainCallExpression(callee)
|
||||
) ||
|
||||
|
||||
// (a?.b)(); (a?.())();
|
||||
(
|
||||
!node.optional &&
|
||||
callee.type === "ChainExpression"
|
||||
)
|
||||
)
|
||||
) {
|
||||
report(node.callee);
|
||||
}
|
||||
|
|
@ -511,7 +525,7 @@ module.exports = {
|
|||
|
||||
if (!shouldSkipLeft && hasExcessParens(node.left)) {
|
||||
if (
|
||||
!(node.left.type === "UnaryExpression" && isExponentiation) &&
|
||||
!(["AwaitExpression", "UnaryExpression"].includes(node.left.type) && isExponentiation) &&
|
||||
!astUtils.isMixedLogicalAndCoalesceExpressions(node.left, node) &&
|
||||
(leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation)) ||
|
||||
isParenthesisedTwice(node.left)
|
||||
|
|
@ -830,45 +844,49 @@ module.exports = {
|
|||
ExportDefaultDeclaration: node => checkExpressionOrExportStatement(node.declaration),
|
||||
ExpressionStatement: node => checkExpressionOrExportStatement(node.expression),
|
||||
|
||||
"ForInStatement, ForOfStatement"(node) {
|
||||
if (node.left.type !== "VariableDeclarator") {
|
||||
ForInStatement(node) {
|
||||
if (node.left.type !== "VariableDeclaration") {
|
||||
const firstLeftToken = sourceCode.getFirstToken(node.left, astUtils.isNotOpeningParenToken);
|
||||
|
||||
if (
|
||||
firstLeftToken.value === "let" && (
|
||||
|
||||
/*
|
||||
* If `let` is the only thing on the left side of the loop, it's the loop variable: `for ((let) of foo);`
|
||||
* Removing it will cause a syntax error, because it will be parsed as the start of a VariableDeclarator.
|
||||
*/
|
||||
(firstLeftToken.range[1] === node.left.range[1] || /*
|
||||
* If `let` is followed by a `[` token, it's a property access on the `let` value: `for ((let[foo]) of bar);`
|
||||
* Removing it will cause the property access to be parsed as a destructuring declaration of `foo` instead.
|
||||
*/
|
||||
astUtils.isOpeningBracketToken(
|
||||
sourceCode.getTokenAfter(firstLeftToken, astUtils.isNotClosingParenToken)
|
||||
))
|
||||
firstLeftToken.value === "let" &&
|
||||
astUtils.isOpeningBracketToken(
|
||||
sourceCode.getTokenAfter(firstLeftToken, astUtils.isNotClosingParenToken)
|
||||
)
|
||||
) {
|
||||
|
||||
// ForInStatement#left expression cannot start with `let[`.
|
||||
tokensToIgnore.add(firstLeftToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type === "ForOfStatement") {
|
||||
const hasExtraParens = node.right.type === "SequenceExpression"
|
||||
? hasDoubleExcessParens(node.right)
|
||||
: hasExcessParens(node.right);
|
||||
if (hasExcessParens(node.left)) {
|
||||
report(node.left);
|
||||
}
|
||||
|
||||
if (hasExtraParens) {
|
||||
report(node.right);
|
||||
}
|
||||
} else if (hasExcessParens(node.right)) {
|
||||
if (hasExcessParens(node.right)) {
|
||||
report(node.right);
|
||||
}
|
||||
},
|
||||
|
||||
ForOfStatement(node) {
|
||||
if (node.left.type !== "VariableDeclaration") {
|
||||
const firstLeftToken = sourceCode.getFirstToken(node.left, astUtils.isNotOpeningParenToken);
|
||||
|
||||
if (firstLeftToken.value === "let") {
|
||||
|
||||
// ForOfStatement#left expression cannot start with `let`.
|
||||
tokensToIgnore.add(firstLeftToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasExcessParens(node.left)) {
|
||||
report(node.left);
|
||||
}
|
||||
|
||||
if (hasExcessParensWithPrecedence(node.right, PRECEDENCE_OF_ASSIGNMENT_EXPR)) {
|
||||
report(node.right);
|
||||
}
|
||||
},
|
||||
|
||||
ForStatement(node) {
|
||||
|
|
@ -881,6 +899,22 @@ module.exports = {
|
|||
}
|
||||
|
||||
if (node.init) {
|
||||
|
||||
if (node.init.type !== "VariableDeclaration") {
|
||||
const firstToken = sourceCode.getFirstToken(node.init, astUtils.isNotOpeningParenToken);
|
||||
|
||||
if (
|
||||
firstToken.value === "let" &&
|
||||
astUtils.isOpeningBracketToken(
|
||||
sourceCode.getTokenAfter(firstToken, astUtils.isNotClosingParenToken)
|
||||
)
|
||||
) {
|
||||
|
||||
// ForStatement#init expression cannot start with `let[`.
|
||||
tokensToIgnore.add(firstToken);
|
||||
}
|
||||
}
|
||||
|
||||
startNewReportsBuffering();
|
||||
|
||||
if (hasExcessParens(node.init)) {
|
||||
|
|
@ -1109,7 +1143,22 @@ module.exports = {
|
|||
},
|
||||
|
||||
UnaryExpression: checkArgumentWithPrecedence,
|
||||
UpdateExpression: checkArgumentWithPrecedence,
|
||||
UpdateExpression(node) {
|
||||
if (node.prefix) {
|
||||
checkArgumentWithPrecedence(node);
|
||||
} else {
|
||||
const { argument } = node;
|
||||
const operatorToken = sourceCode.getLastToken(node);
|
||||
|
||||
if (argument.loc.end.line === operatorToken.loc.start.line) {
|
||||
checkArgumentWithPrecedence(node);
|
||||
} else {
|
||||
if (hasDoubleExcessParens(argument)) {
|
||||
report(argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
AwaitExpression: checkArgumentWithPrecedence,
|
||||
|
||||
VariableDeclarator(node) {
|
||||
|
|
|
|||
31
node_modules/eslint/lib/rules/no-fallthrough.js
generated
vendored
31
node_modules/eslint/lib/rules/no-fallthrough.js
generated
vendored
|
|
@ -4,12 +4,6 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -17,15 +11,26 @@ const lodash = require("lodash");
|
|||
const DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/iu;
|
||||
|
||||
/**
|
||||
* Checks whether or not a given node has a fallthrough comment.
|
||||
* @param {ASTNode} node A SwitchCase node to get comments.
|
||||
* Checks whether or not a given case has a fallthrough comment.
|
||||
* @param {ASTNode} caseWhichFallsThrough SwitchCase node which falls through.
|
||||
* @param {ASTNode} subsequentCase The case after caseWhichFallsThrough.
|
||||
* @param {RuleContext} context A rule context which stores comments.
|
||||
* @param {RegExp} fallthroughCommentPattern A pattern to match comment to.
|
||||
* @returns {boolean} `true` if the node has a valid fallthrough comment.
|
||||
* @returns {boolean} `true` if the case has a valid fallthrough comment.
|
||||
*/
|
||||
function hasFallthroughComment(node, context, fallthroughCommentPattern) {
|
||||
function hasFallthroughComment(caseWhichFallsThrough, subsequentCase, context, fallthroughCommentPattern) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
const comment = lodash.last(sourceCode.getCommentsBefore(node));
|
||||
|
||||
if (caseWhichFallsThrough.consequent.length === 1 && caseWhichFallsThrough.consequent[0].type === "BlockStatement") {
|
||||
const trailingCloseBrace = sourceCode.getLastToken(caseWhichFallsThrough.consequent[0]);
|
||||
const commentInBlock = sourceCode.getCommentsBefore(trailingCloseBrace).pop();
|
||||
|
||||
if (commentInBlock && fallthroughCommentPattern.test(commentInBlock.value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const comment = sourceCode.getCommentsBefore(subsequentCase).pop();
|
||||
|
||||
return Boolean(comment && fallthroughCommentPattern.test(comment.value));
|
||||
}
|
||||
|
|
@ -114,7 +119,7 @@ module.exports = {
|
|||
* Checks whether or not there is a fallthrough comment.
|
||||
* And reports the previous fallthrough node if that does not exist.
|
||||
*/
|
||||
if (fallthroughCase && !hasFallthroughComment(node, context, fallthroughCommentPattern)) {
|
||||
if (fallthroughCase && !hasFallthroughComment(fallthroughCase, node, context, fallthroughCommentPattern)) {
|
||||
context.report({
|
||||
messageId: node.test ? "case" : "default",
|
||||
node
|
||||
|
|
@ -133,7 +138,7 @@ module.exports = {
|
|||
*/
|
||||
if (currentCodePath.currentSegments.some(isReachable) &&
|
||||
(node.consequent.length > 0 || hasBlankLinesBetween(node, nextToken)) &&
|
||||
lodash.last(node.parent.cases) !== node) {
|
||||
node.parent.cases[node.parent.cases.length - 1] !== node) {
|
||||
fallthroughCase = node;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
60
node_modules/eslint/lib/rules/no-implicit-coercion.js
generated
vendored
60
node_modules/eslint/lib/rules/no-implicit-coercion.js
generated
vendored
|
|
@ -24,6 +24,7 @@ function parseOptions(options) {
|
|||
boolean: "boolean" in options ? options.boolean : true,
|
||||
number: "number" in options ? options.number : true,
|
||||
string: "string" in options ? options.string : true,
|
||||
disallowTemplateShorthand: "disallowTemplateShorthand" in options ? options.disallowTemplateShorthand : false,
|
||||
allow: options.allow || []
|
||||
};
|
||||
}
|
||||
|
|
@ -108,6 +109,20 @@ function getNonNumericOperand(node) {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an expression evaluates to a string.
|
||||
* @param {ASTNode} node node that represents the expression to check.
|
||||
* @returns {boolean} Whether or not the expression evaluates to a string.
|
||||
*/
|
||||
function isStringType(node) {
|
||||
return astUtils.isStringLiteral(node) ||
|
||||
(
|
||||
node.type === "CallExpression" &&
|
||||
node.callee.type === "Identifier" &&
|
||||
node.callee.name === "String"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a node is an empty string literal or not.
|
||||
* @param {ASTNode} node The node to check.
|
||||
|
|
@ -125,8 +140,8 @@ function isEmptyString(node) {
|
|||
*/
|
||||
function isConcatWithEmptyString(node) {
|
||||
return node.operator === "+" && (
|
||||
(isEmptyString(node.left) && !astUtils.isStringLiteral(node.right)) ||
|
||||
(isEmptyString(node.right) && !astUtils.isStringLiteral(node.left))
|
||||
(isEmptyString(node.left) && !isStringType(node.right)) ||
|
||||
(isEmptyString(node.right) && !isStringType(node.left))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -180,6 +195,10 @@ module.exports = {
|
|||
type: "boolean",
|
||||
default: true
|
||||
},
|
||||
disallowTemplateShorthand: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
},
|
||||
allow: {
|
||||
type: "array",
|
||||
items: {
|
||||
|
|
@ -299,6 +318,43 @@ module.exports = {
|
|||
|
||||
report(node, recommendation, true);
|
||||
}
|
||||
},
|
||||
|
||||
TemplateLiteral(node) {
|
||||
if (!options.disallowTemplateShorthand) {
|
||||
return;
|
||||
}
|
||||
|
||||
// tag`${foo}`
|
||||
if (node.parent.type === "TaggedTemplateExpression") {
|
||||
return;
|
||||
}
|
||||
|
||||
// `` or `${foo}${bar}`
|
||||
if (node.expressions.length !== 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// `prefix${foo}`
|
||||
if (node.quasis[0].value.cooked !== "") {
|
||||
return;
|
||||
}
|
||||
|
||||
// `${foo}postfix`
|
||||
if (node.quasis[1].value.cooked !== "") {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the expression is already a string, then this isn't a coercion
|
||||
if (isStringType(node.expressions[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
const code = sourceCode.getText(node.expressions[0]);
|
||||
const recommendation = `String(${code})`;
|
||||
|
||||
report(node, recommendation, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
8
node_modules/eslint/lib/rules/no-import-assign.js
generated
vendored
8
node_modules/eslint/lib/rules/no-import-assign.js
generated
vendored
|
|
@ -97,10 +97,10 @@ function isIterationVariable(node) {
|
|||
* - `Object.defineProperties`
|
||||
* - `Object.freeze`
|
||||
* - `Object.setPrototypeOf`
|
||||
* - `Refrect.defineProperty`
|
||||
* - `Refrect.deleteProperty`
|
||||
* - `Refrect.set`
|
||||
* - `Refrect.setPrototypeOf`
|
||||
* - `Reflect.defineProperty`
|
||||
* - `Reflect.deleteProperty`
|
||||
* - `Reflect.set`
|
||||
* - `Reflect.setPrototypeOf`
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @param {Scope} scope A `escope.Scope` object to find variable (whichever).
|
||||
* @returns {boolean} `true` if the node is at the first argument of a well-known mutation function.
|
||||
|
|
|
|||
29
node_modules/eslint/lib/rules/no-inline-comments.js
generated
vendored
29
node_modules/eslint/lib/rules/no-inline-comments.js
generated
vendored
|
|
@ -21,7 +21,17 @@ module.exports = {
|
|||
url: "https://eslint.org/docs/rules/no-inline-comments"
|
||||
},
|
||||
|
||||
schema: [],
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
ignorePattern: {
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
],
|
||||
|
||||
messages: {
|
||||
unexpectedInlineComment: "Unexpected comment inline with code."
|
||||
|
|
@ -30,6 +40,12 @@ module.exports = {
|
|||
|
||||
create(context) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
const options = context.options[0];
|
||||
let customIgnoreRegExp;
|
||||
|
||||
if (options && options.ignorePattern) {
|
||||
customIgnoreRegExp = new RegExp(options.ignorePattern, "u");
|
||||
}
|
||||
|
||||
/**
|
||||
* Will check that comments are not on lines starting with or ending with code
|
||||
|
|
@ -51,6 +67,11 @@ module.exports = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Matches the ignore pattern
|
||||
if (customIgnoreRegExp && customIgnoreRegExp.test(node.value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// JSX Exception
|
||||
if (
|
||||
(isPreambleEmpty || preamble === "{") &&
|
||||
|
|
@ -80,9 +101,9 @@ module.exports = {
|
|||
|
||||
return {
|
||||
Program() {
|
||||
const comments = sourceCode.getAllComments();
|
||||
|
||||
comments.filter(token => token.type !== "Shebang").forEach(testCodeAroundComment);
|
||||
sourceCode.getAllComments()
|
||||
.filter(token => token.type !== "Shebang")
|
||||
.forEach(testCodeAroundComment);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
45
node_modules/eslint/lib/rules/no-invalid-regexp.js
generated
vendored
45
node_modules/eslint/lib/rules/no-invalid-regexp.js
generated
vendored
|
|
@ -9,7 +9,7 @@
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
const RegExpValidator = require("regexpp").RegExpValidator;
|
||||
const validator = new RegExpValidator({ ecmaVersion: 2018 });
|
||||
const validator = new RegExpValidator();
|
||||
const validFlags = /[gimuys]/gu;
|
||||
const undefined1 = void 0;
|
||||
|
||||
|
|
@ -69,6 +69,28 @@ module.exports = {
|
|||
return node && node.type === "Literal" && typeof node.value === "string";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets flags of a regular expression created by the given `RegExp()` or `new RegExp()` call
|
||||
* Examples:
|
||||
* new RegExp(".") // => ""
|
||||
* new RegExp(".", "gu") // => "gu"
|
||||
* new RegExp(".", flags) // => null
|
||||
* @param {ASTNode} node `CallExpression` or `NewExpression` node
|
||||
* @returns {string|null} flags if they can be determined, `null` otherwise
|
||||
* @private
|
||||
*/
|
||||
function getFlags(node) {
|
||||
if (node.arguments.length < 2) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (isString(node.arguments[1])) {
|
||||
return node.arguments[1].value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check syntax error in a given pattern.
|
||||
* @param {string} pattern The RegExp pattern to validate.
|
||||
|
|
@ -104,18 +126,23 @@ module.exports = {
|
|||
return;
|
||||
}
|
||||
const pattern = node.arguments[0].value;
|
||||
let flags = isString(node.arguments[1]) ? node.arguments[1].value : "";
|
||||
let flags = getFlags(node);
|
||||
|
||||
if (allowedFlags) {
|
||||
if (flags && allowedFlags) {
|
||||
flags = flags.replace(allowedFlags, "");
|
||||
}
|
||||
|
||||
// If flags are unknown, check both are errored or not.
|
||||
const message = validateRegExpFlags(flags) || (
|
||||
flags
|
||||
? validateRegExpPattern(pattern, flags.indexOf("u") !== -1)
|
||||
: validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false)
|
||||
);
|
||||
const message =
|
||||
(
|
||||
flags && validateRegExpFlags(flags)
|
||||
) ||
|
||||
(
|
||||
|
||||
// If flags are unknown, report the regex only if its pattern is invalid both with and without the "u" flag
|
||||
flags === null
|
||||
? validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false)
|
||||
: validateRegExpPattern(pattern, flags.includes("u"))
|
||||
);
|
||||
|
||||
if (message) {
|
||||
context.report({
|
||||
|
|
|
|||
16
node_modules/eslint/lib/rules/no-irregular-whitespace.js
generated
vendored
16
node_modules/eslint/lib/rules/no-irregular-whitespace.js
generated
vendored
|
|
@ -82,7 +82,7 @@ module.exports = {
|
|||
const commentNodes = sourceCode.getAllComments();
|
||||
|
||||
/**
|
||||
* Removes errors that occur inside a string node
|
||||
* Removes errors that occur inside the given node
|
||||
* @param {ASTNode} node to check for matching errors.
|
||||
* @returns {void}
|
||||
* @private
|
||||
|
|
@ -91,14 +91,12 @@ module.exports = {
|
|||
const locStart = node.loc.start;
|
||||
const locEnd = node.loc.end;
|
||||
|
||||
errors = errors.filter(({ loc: { start: errorLoc } }) => {
|
||||
if (errorLoc.line >= locStart.line && errorLoc.line <= locEnd.line) {
|
||||
if (errorLoc.column >= locStart.column && (errorLoc.column <= locEnd.column || errorLoc.line < locEnd.line)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
errors = errors.filter(({ loc: { start: errorLocStart } }) => (
|
||||
errorLocStart.line < locStart.line ||
|
||||
errorLocStart.line === locStart.line && errorLocStart.column < locStart.column ||
|
||||
errorLocStart.line === locEnd.line && errorLocStart.column >= locEnd.column ||
|
||||
errorLocStart.line > locEnd.line
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
8
node_modules/eslint/lib/rules/no-loss-of-precision.js
generated
vendored
8
node_modules/eslint/lib/rules/no-loss-of-precision.js
generated
vendored
|
|
@ -105,9 +105,9 @@ module.exports = {
|
|||
}
|
||||
|
||||
/**
|
||||
* Converts an integer to to an object containing the the integer's coefficient and order of magnitude
|
||||
* Converts an integer to to an object containing the integer's coefficient and order of magnitude
|
||||
* @param {string} stringInteger the string representation of the integer being converted
|
||||
* @returns {Object} the object containing the the integer's coefficient and order of magnitude
|
||||
* @returns {Object} the object containing the integer's coefficient and order of magnitude
|
||||
*/
|
||||
function normalizeInteger(stringInteger) {
|
||||
const significantDigits = removeTrailingZeros(removeLeadingZeros(stringInteger));
|
||||
|
|
@ -120,9 +120,9 @@ module.exports = {
|
|||
|
||||
/**
|
||||
*
|
||||
* Converts a float to to an object containing the the floats's coefficient and order of magnitude
|
||||
* Converts a float to to an object containing the floats's coefficient and order of magnitude
|
||||
* @param {string} stringFloat the string representation of the float being converted
|
||||
* @returns {Object} the object containing the the integer's coefficient and order of magnitude
|
||||
* @returns {Object} the object containing the integer's coefficient and order of magnitude
|
||||
*/
|
||||
function normalizeFloat(stringFloat) {
|
||||
const trimmedFloat = removeLeadingZeros(stringFloat);
|
||||
|
|
|
|||
31
node_modules/eslint/lib/rules/no-mixed-operators.js
generated
vendored
31
node_modules/eslint/lib/rules/no-mixed-operators.js
generated
vendored
|
|
@ -117,7 +117,7 @@ module.exports = {
|
|||
],
|
||||
|
||||
messages: {
|
||||
unexpectedMixedOperator: "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'."
|
||||
unexpectedMixedOperator: "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'. Use parentheses to clarify the intended order of operations."
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -161,17 +161,6 @@ module.exports = {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the operator of a given node is mixed with a
|
||||
* conditional expression.
|
||||
* @param {ASTNode} node A node to check. This is a conditional
|
||||
* expression node
|
||||
* @returns {boolean} `true` if the node was mixed.
|
||||
*/
|
||||
function isMixedWithConditionalParent(node) {
|
||||
return !astUtils.isParenthesised(sourceCode, node) && !astUtils.isParenthesised(sourceCode, node.test);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the operator token of a given node.
|
||||
* @param {ASTNode} node A node to check. This is a BinaryExpression
|
||||
|
|
@ -220,19 +209,13 @@ module.exports = {
|
|||
* @returns {void}
|
||||
*/
|
||||
function check(node) {
|
||||
if (TARGET_NODE_TYPE.test(node.parent.type)) {
|
||||
if (node.parent.type === "ConditionalExpression" && !shouldIgnore(node) && isMixedWithConditionalParent(node.parent)) {
|
||||
reportBothOperators(node);
|
||||
} else {
|
||||
if (TARGET_NODE_TYPE.test(node.parent.type) &&
|
||||
isMixedWithParent(node) &&
|
||||
!shouldIgnore(node)
|
||||
) {
|
||||
reportBothOperators(node);
|
||||
}
|
||||
}
|
||||
if (
|
||||
TARGET_NODE_TYPE.test(node.parent.type) &&
|
||||
isMixedWithParent(node) &&
|
||||
!shouldIgnore(node)
|
||||
) {
|
||||
reportBothOperators(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
17
node_modules/eslint/lib/rules/no-multi-assign.js
generated
vendored
17
node_modules/eslint/lib/rules/no-multi-assign.js
generated
vendored
|
|
@ -21,7 +21,16 @@ module.exports = {
|
|||
url: "https://eslint.org/docs/rules/no-multi-assign"
|
||||
},
|
||||
|
||||
schema: [],
|
||||
schema: [{
|
||||
type: "object",
|
||||
properties: {
|
||||
ignoreNonDeclaration: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}],
|
||||
|
||||
messages: {
|
||||
unexpectedChain: "Unexpected chained assignment."
|
||||
|
|
@ -33,10 +42,14 @@ module.exports = {
|
|||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
const options = context.options[0] || {
|
||||
ignoreNonDeclaration: false
|
||||
};
|
||||
const targetParent = options.ignoreNonDeclaration ? ["VariableDeclarator"] : ["AssignmentExpression", "VariableDeclarator"];
|
||||
|
||||
return {
|
||||
AssignmentExpression(node) {
|
||||
if (["AssignmentExpression", "VariableDeclarator"].indexOf(node.parent.type) !== -1) {
|
||||
if (targetParent.indexOf(node.parent.type) !== -1) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unexpectedChain"
|
||||
|
|
|
|||
147
node_modules/eslint/lib/rules/no-nonoctal-decimal-escape.js
generated
vendored
Normal file
147
node_modules/eslint/lib/rules/no-nonoctal-decimal-escape.js
generated
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/**
|
||||
* @fileoverview Rule to disallow `\8` and `\9` escape sequences in string literals.
|
||||
* @author Milos Djermanovic
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const QUICK_TEST_REGEX = /\\[89]/u;
|
||||
|
||||
/**
|
||||
* Returns unicode escape sequence that represents the given character.
|
||||
* @param {string} character A single code unit.
|
||||
* @returns {string} "\uXXXX" sequence.
|
||||
*/
|
||||
function getUnicodeEscape(character) {
|
||||
return `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "disallow `\\8` and `\\9` escape sequences in string literals",
|
||||
category: "Best Practices",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/no-nonoctal-decimal-escape",
|
||||
suggestion: true
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
decimalEscape: "Don't use '{{decimalEscape}}' escape sequence.",
|
||||
|
||||
// suggestions
|
||||
refactor: "Replace '{{original}}' with '{{replacement}}'. This maintains the current functionality.",
|
||||
escapeBackslash: "Replace '{{original}}' with '{{replacement}}' to include the actual backslash character."
|
||||
}
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
/**
|
||||
* Creates a new Suggestion object.
|
||||
* @param {string} messageId "refactor" or "escapeBackslash".
|
||||
* @param {int[]} range The range to replace.
|
||||
* @param {string} replacement New text for the range.
|
||||
* @returns {Object} Suggestion
|
||||
*/
|
||||
function createSuggestion(messageId, range, replacement) {
|
||||
return {
|
||||
messageId,
|
||||
data: {
|
||||
original: sourceCode.getText().slice(...range),
|
||||
replacement
|
||||
},
|
||||
fix(fixer) {
|
||||
return fixer.replaceTextRange(range, replacement);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
Literal(node) {
|
||||
if (typeof node.value !== "string") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QUICK_TEST_REGEX.test(node.raw)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const regex = /(?:[^\\]|(?<previousEscape>\\.))*?(?<decimalEscape>\\[89])/suy;
|
||||
let match;
|
||||
|
||||
while ((match = regex.exec(node.raw))) {
|
||||
const { previousEscape, decimalEscape } = match.groups;
|
||||
const decimalEscapeRangeEnd = node.range[0] + match.index + match[0].length;
|
||||
const decimalEscapeRangeStart = decimalEscapeRangeEnd - decimalEscape.length;
|
||||
const decimalEscapeRange = [decimalEscapeRangeStart, decimalEscapeRangeEnd];
|
||||
const suggest = [];
|
||||
|
||||
// When `regex` is matched, `previousEscape` can only capture characters adjacent to `decimalEscape`
|
||||
if (previousEscape === "\\0") {
|
||||
|
||||
/*
|
||||
* Now we have a NULL escape "\0" immediately followed by a decimal escape, e.g.: "\0\8".
|
||||
* Fixing this to "\08" would turn "\0" into a legacy octal escape. To avoid producing
|
||||
* an octal escape while fixing a decimal escape, we provide different suggestions.
|
||||
*/
|
||||
suggest.push(
|
||||
createSuggestion( // "\0\8" -> "\u00008"
|
||||
"refactor",
|
||||
[decimalEscapeRangeStart - previousEscape.length, decimalEscapeRangeEnd],
|
||||
`${getUnicodeEscape("\0")}${decimalEscape[1]}`
|
||||
),
|
||||
createSuggestion( // "\8" -> "\u0038"
|
||||
"refactor",
|
||||
decimalEscapeRange,
|
||||
getUnicodeEscape(decimalEscape[1])
|
||||
)
|
||||
);
|
||||
} else {
|
||||
suggest.push(
|
||||
createSuggestion( // "\8" -> "8"
|
||||
"refactor",
|
||||
decimalEscapeRange,
|
||||
decimalEscape[1]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
suggest.push(
|
||||
createSuggestion( // "\8" -> "\\8"
|
||||
"escapeBackslash",
|
||||
decimalEscapeRange,
|
||||
`\\${decimalEscape}`
|
||||
)
|
||||
);
|
||||
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
start: sourceCode.getLocFromIndex(decimalEscapeRangeStart),
|
||||
end: sourceCode.getLocFromIndex(decimalEscapeRangeEnd)
|
||||
},
|
||||
messageId: "decimalEscape",
|
||||
data: {
|
||||
decimalEscape
|
||||
},
|
||||
suggest
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
8
node_modules/eslint/lib/rules/no-prototype-builtins.js
generated
vendored
8
node_modules/eslint/lib/rules/no-prototype-builtins.js
generated
vendored
|
|
@ -46,15 +46,15 @@ module.exports = {
|
|||
*/
|
||||
function disallowBuiltIns(node) {
|
||||
|
||||
// TODO: just use `astUtils.getStaticPropertyName(node.callee)`
|
||||
const callee = astUtils.skipChainExpression(node.callee);
|
||||
|
||||
if (callee.type !== "MemberExpression" || callee.computed) {
|
||||
if (callee.type !== "MemberExpression") {
|
||||
return;
|
||||
}
|
||||
const propName = callee.property.name;
|
||||
|
||||
if (DISALLOWED_PROPS.indexOf(propName) > -1) {
|
||||
const propName = astUtils.getStaticPropertyName(callee);
|
||||
|
||||
if (propName !== null && DISALLOWED_PROPS.indexOf(propName) > -1) {
|
||||
context.report({
|
||||
messageId: "prototypeBuildIn",
|
||||
loc: callee.property.loc,
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/no-restricted-exports.js
generated
vendored
2
node_modules/eslint/lib/rules/no-restricted-exports.js
generated
vendored
|
|
@ -45,7 +45,7 @@ module.exports = {
|
|||
|
||||
/**
|
||||
* Checks and reports given exported identifier.
|
||||
* @param {ASTNode} node exported `Identifer` node to check.
|
||||
* @param {ASTNode} node exported `Identifier` node to check.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkExportedName(node) {
|
||||
|
|
|
|||
85
node_modules/eslint/lib/rules/no-restricted-imports.js
generated
vendored
85
node_modules/eslint/lib/rules/no-restricted-imports.js
generated
vendored
|
|
@ -10,12 +10,6 @@
|
|||
|
||||
const ignore = require("ignore");
|
||||
|
||||
const arrayOfStrings = {
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
uniqueItems: true
|
||||
};
|
||||
|
||||
const arrayOfStringsOrObjects = {
|
||||
type: "array",
|
||||
items: {
|
||||
|
|
@ -44,6 +38,41 @@ const arrayOfStringsOrObjects = {
|
|||
uniqueItems: true
|
||||
};
|
||||
|
||||
const arrayOfStringsOrObjectPatterns = {
|
||||
anyOf: [
|
||||
{
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string"
|
||||
},
|
||||
uniqueItems: true
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
group: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string"
|
||||
},
|
||||
minItems: 1,
|
||||
uniqueItems: true
|
||||
},
|
||||
message: {
|
||||
type: "string",
|
||||
minLength: 1
|
||||
}
|
||||
},
|
||||
additionalProperties: false,
|
||||
required: ["group"]
|
||||
},
|
||||
uniqueItems: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
|
@ -61,6 +90,8 @@ module.exports = {
|
|||
pathWithCustomMessage: "'{{importSource}}' import is restricted from being used. {{customMessage}}",
|
||||
|
||||
patterns: "'{{importSource}}' import is restricted from being used by a pattern.",
|
||||
// eslint-disable-next-line eslint-plugin/report-message-format
|
||||
patternWithCustomMessage: "'{{importSource}}' import is restricted from being used by a pattern. {{customMessage}}",
|
||||
|
||||
everything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
|
||||
// eslint-disable-next-line eslint-plugin/report-message-format
|
||||
|
|
@ -80,7 +111,7 @@ module.exports = {
|
|||
type: "object",
|
||||
properties: {
|
||||
paths: arrayOfStringsOrObjects,
|
||||
patterns: arrayOfStrings
|
||||
patterns: arrayOfStringsOrObjectPatterns
|
||||
},
|
||||
additionalProperties: false
|
||||
}],
|
||||
|
|
@ -98,13 +129,6 @@ module.exports = {
|
|||
(Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns"));
|
||||
|
||||
const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
|
||||
const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
|
||||
|
||||
// if no imports are restricted we don"t need to check
|
||||
if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const restrictedPathMessages = restrictedPaths.reduce((memo, importSource) => {
|
||||
if (typeof importSource === "string") {
|
||||
memo[importSource] = { message: null };
|
||||
|
|
@ -117,7 +141,16 @@ module.exports = {
|
|||
return memo;
|
||||
}, {});
|
||||
|
||||
const restrictedPatternsMatcher = ignore().add(restrictedPatterns);
|
||||
// Handle patterns too, either as strings or groups
|
||||
const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
|
||||
const restrictedPatternGroups = restrictedPatterns.length > 0 && typeof restrictedPatterns[0] === "string"
|
||||
? [{ matcher: ignore().add(restrictedPatterns) }]
|
||||
: restrictedPatterns.map(({ group, message }) => ({ matcher: ignore().add(group), customMessage: message }));
|
||||
|
||||
// if no imports are restricted we don"t need to check
|
||||
if (Object.keys(restrictedPaths).length === 0 && restrictedPatternGroups.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a restricted path.
|
||||
|
|
@ -184,17 +217,19 @@ module.exports = {
|
|||
/**
|
||||
* Report a restricted path specifically for patterns.
|
||||
* @param {node} node representing the restricted path reference
|
||||
* @param {Object} group contains a Ignore instance for paths, and the customMessage to show if it fails
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function reportPathForPatterns(node) {
|
||||
function reportPathForPatterns(node, group) {
|
||||
const importSource = node.source.value.trim();
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: "patterns",
|
||||
messageId: group.customMessage ? "patternWithCustomMessage" : "patterns",
|
||||
data: {
|
||||
importSource
|
||||
importSource,
|
||||
customMessage: group.customMessage
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -202,11 +237,12 @@ module.exports = {
|
|||
/**
|
||||
* Check if the given importSource is restricted by a pattern.
|
||||
* @param {string} importSource path of the import
|
||||
* @param {Object} group contains a Ignore instance for paths, and the customMessage to show if it fails
|
||||
* @returns {boolean} whether the variable is a restricted pattern or not
|
||||
* @private
|
||||
*/
|
||||
function isRestrictedPattern(importSource) {
|
||||
return restrictedPatterns.length > 0 && restrictedPatternsMatcher.ignores(importSource);
|
||||
function isRestrictedPattern(importSource, group) {
|
||||
return group.matcher.ignores(importSource);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -249,10 +285,11 @@ module.exports = {
|
|||
}
|
||||
|
||||
checkRestrictedPathAndReport(importSource, importNames, node);
|
||||
|
||||
if (isRestrictedPattern(importSource)) {
|
||||
reportPathForPatterns(node);
|
||||
}
|
||||
restrictedPatternGroups.forEach(group => {
|
||||
if (isRestrictedPattern(importSource, group)) {
|
||||
reportPathForPatterns(node, group);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
28
node_modules/eslint/lib/rules/no-script-url.js
generated
vendored
28
node_modules/eslint/lib/rules/no-script-url.js
generated
vendored
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -31,18 +33,30 @@ module.exports = {
|
|||
|
||||
create(context) {
|
||||
|
||||
return {
|
||||
/**
|
||||
* Check whether a node's static value starts with "javascript:" or not.
|
||||
* And report an error for unexpected script URL.
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {void}
|
||||
*/
|
||||
function check(node) {
|
||||
const value = astUtils.getStaticStringValue(node);
|
||||
|
||||
if (typeof value === "string" && value.toLowerCase().indexOf("javascript:") === 0) {
|
||||
context.report({ node, messageId: "unexpectedScriptURL" });
|
||||
}
|
||||
}
|
||||
return {
|
||||
Literal(node) {
|
||||
if (node.value && typeof node.value === "string") {
|
||||
const value = node.value.toLowerCase();
|
||||
|
||||
if (value.indexOf("javascript:") === 0) {
|
||||
context.report({ node, messageId: "unexpectedScriptURL" });
|
||||
}
|
||||
check(node);
|
||||
}
|
||||
},
|
||||
TemplateLiteral(node) {
|
||||
if (!(node.parent && node.parent.type === "TaggedTemplateExpression")) {
|
||||
check(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
|||
35
node_modules/eslint/lib/rules/no-sequences.js
generated
vendored
35
node_modules/eslint/lib/rules/no-sequences.js
generated
vendored
|
|
@ -11,6 +11,14 @@
|
|||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
allowInParentheses: true
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -26,7 +34,15 @@ module.exports = {
|
|||
url: "https://eslint.org/docs/rules/no-sequences"
|
||||
},
|
||||
|
||||
schema: [],
|
||||
schema: [{
|
||||
properties: {
|
||||
allowInParentheses: {
|
||||
type: "boolean",
|
||||
default: true
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}],
|
||||
|
||||
messages: {
|
||||
unexpectedCommaExpression: "Unexpected use of comma operator."
|
||||
|
|
@ -34,6 +50,7 @@ module.exports = {
|
|||
},
|
||||
|
||||
create(context) {
|
||||
const options = Object.assign({}, DEFAULT_OPTIONS, context.options[0]);
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
/**
|
||||
|
|
@ -99,13 +116,15 @@ module.exports = {
|
|||
}
|
||||
|
||||
// Wrapping a sequence in extra parens indicates intent
|
||||
if (requiresExtraParens(node)) {
|
||||
if (isParenthesisedTwice(node)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (isParenthesised(node)) {
|
||||
return;
|
||||
if (options.allowInParentheses) {
|
||||
if (requiresExtraParens(node)) {
|
||||
if (isParenthesisedTwice(node)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (isParenthesised(node)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
38
node_modules/eslint/lib/rules/no-shadow.js
generated
vendored
38
node_modules/eslint/lib/rules/no-shadow.js
generated
vendored
|
|
@ -44,7 +44,8 @@ module.exports = {
|
|||
],
|
||||
|
||||
messages: {
|
||||
noShadow: "'{{name}}' is already declared in the upper scope."
|
||||
noShadow: "'{{name}}' is already declared in the upper scope on line {{shadowedLine}} column {{shadowedColumn}}.",
|
||||
noShadowGlobal: "'{{name}}' is already a global variable."
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -117,6 +118,29 @@ module.exports = {
|
|||
return def && def.name.range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get declared line and column of a variable.
|
||||
* @param {eslint-scope.Variable} variable The variable to get.
|
||||
* @returns {Object} The declared line and column of the variable.
|
||||
*/
|
||||
function getDeclaredLocation(variable) {
|
||||
const identifier = variable.identifiers[0];
|
||||
let obj;
|
||||
|
||||
if (identifier) {
|
||||
obj = {
|
||||
global: false,
|
||||
line: identifier.loc.start.line,
|
||||
column: identifier.loc.start.column + 1
|
||||
};
|
||||
} else {
|
||||
obj = {
|
||||
global: true
|
||||
};
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a variable is in TDZ of scopeVar.
|
||||
* @param {Object} variable The variable to check.
|
||||
|
|
@ -165,10 +189,18 @@ module.exports = {
|
|||
!isOnInitializer(variable, shadowed) &&
|
||||
!(options.hoist !== "all" && isInTdz(variable, shadowed))
|
||||
) {
|
||||
const location = getDeclaredLocation(shadowed);
|
||||
const messageId = location.global ? "noShadowGlobal" : "noShadow";
|
||||
const data = { name: variable.name };
|
||||
|
||||
if (!location.global) {
|
||||
data.shadowedLine = location.line;
|
||||
data.shadowedColumn = location.column;
|
||||
}
|
||||
context.report({
|
||||
node: variable.identifiers[0],
|
||||
messageId: "noShadow",
|
||||
data: variable
|
||||
messageId,
|
||||
data
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/no-this-before-super.js
generated
vendored
2
node_modules/eslint/lib/rules/no-this-before-super.js
generated
vendored
|
|
@ -171,7 +171,7 @@ module.exports = {
|
|||
/**
|
||||
* Removes the top of stack item.
|
||||
*
|
||||
* And this treverses all segments of this code path then reports every
|
||||
* And this traverses all segments of this code path then reports every
|
||||
* invalid node.
|
||||
* @param {CodePath} codePath A code path which was ended.
|
||||
* @returns {void}
|
||||
|
|
|
|||
205
node_modules/eslint/lib/rules/no-unsafe-optional-chaining.js
generated
vendored
Normal file
205
node_modules/eslint/lib/rules/no-unsafe-optional-chaining.js
generated
vendored
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/**
|
||||
* @fileoverview Rule to disallow unsafe optional chaining
|
||||
* @author Yeon JuAn
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const UNSAFE_ARITHMETIC_OPERATORS = new Set(["+", "-", "/", "*", "%", "**"]);
|
||||
const UNSAFE_ASSIGNMENT_OPERATORS = new Set(["+=", "-=", "/=", "*=", "%=", "**="]);
|
||||
const UNSAFE_RELATIONAL_OPERATORS = new Set(["in", "instanceof"]);
|
||||
|
||||
/**
|
||||
* Checks whether a node is a destructuring pattern or not
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {boolean} `true` if a node is a destructuring pattern, otherwise `false`
|
||||
*/
|
||||
function isDestructuringPattern(node) {
|
||||
return node.type === "ObjectPattern" || node.type === "ArrayPattern";
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "disallow use of optional chaining in contexts where the `undefined` value is not allowed",
|
||||
category: "Possible Errors",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/no-unsafe-optional-chaining"
|
||||
},
|
||||
schema: [{
|
||||
type: "object",
|
||||
properties: {
|
||||
disallowArithmeticOperators: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}],
|
||||
fixable: null,
|
||||
messages: {
|
||||
unsafeOptionalChain: "Unsafe usage of optional chaining. If it short-circuits with 'undefined' the evaluation will throw TypeError.",
|
||||
unsafeArithmetic: "Unsafe arithmetic operation on optional chaining. It can result in NaN."
|
||||
}
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const options = context.options[0] || {};
|
||||
const disallowArithmeticOperators = (options.disallowArithmeticOperators) || false;
|
||||
|
||||
/**
|
||||
* Reports unsafe usage of optional chaining
|
||||
* @param {ASTNode} node node to report
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportUnsafeUsage(node) {
|
||||
context.report({
|
||||
messageId: "unsafeOptionalChain",
|
||||
node
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports unsafe arithmetic operation on optional chaining
|
||||
* @param {ASTNode} node node to report
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportUnsafeArithmetic(node) {
|
||||
context.report({
|
||||
messageId: "unsafeArithmetic",
|
||||
node
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and reports if a node can short-circuit with `undefined` by optional chaining.
|
||||
* @param {ASTNode} [node] node to check
|
||||
* @param {Function} reportFunc report function
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkUndefinedShortCircuit(node, reportFunc) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
switch (node.type) {
|
||||
case "LogicalExpression":
|
||||
if (node.operator === "||" || node.operator === "??") {
|
||||
checkUndefinedShortCircuit(node.right, reportFunc);
|
||||
} else if (node.operator === "&&") {
|
||||
checkUndefinedShortCircuit(node.left, reportFunc);
|
||||
checkUndefinedShortCircuit(node.right, reportFunc);
|
||||
}
|
||||
break;
|
||||
case "SequenceExpression":
|
||||
checkUndefinedShortCircuit(
|
||||
node.expressions[node.expressions.length - 1],
|
||||
reportFunc
|
||||
);
|
||||
break;
|
||||
case "ConditionalExpression":
|
||||
checkUndefinedShortCircuit(node.consequent, reportFunc);
|
||||
checkUndefinedShortCircuit(node.alternate, reportFunc);
|
||||
break;
|
||||
case "AwaitExpression":
|
||||
checkUndefinedShortCircuit(node.argument, reportFunc);
|
||||
break;
|
||||
case "ChainExpression":
|
||||
reportFunc(node);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks unsafe usage of optional chaining
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkUnsafeUsage(node) {
|
||||
checkUndefinedShortCircuit(node, reportUnsafeUsage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks unsafe arithmetic operations on optional chaining
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkUnsafeArithmetic(node) {
|
||||
checkUndefinedShortCircuit(node, reportUnsafeArithmetic);
|
||||
}
|
||||
|
||||
return {
|
||||
"AssignmentExpression, AssignmentPattern"(node) {
|
||||
if (isDestructuringPattern(node.left)) {
|
||||
checkUnsafeUsage(node.right);
|
||||
}
|
||||
},
|
||||
"ClassDeclaration, ClassExpression"(node) {
|
||||
checkUnsafeUsage(node.superClass);
|
||||
},
|
||||
CallExpression(node) {
|
||||
if (!node.optional) {
|
||||
checkUnsafeUsage(node.callee);
|
||||
}
|
||||
},
|
||||
NewExpression(node) {
|
||||
checkUnsafeUsage(node.callee);
|
||||
},
|
||||
VariableDeclarator(node) {
|
||||
if (isDestructuringPattern(node.id)) {
|
||||
checkUnsafeUsage(node.init);
|
||||
}
|
||||
},
|
||||
MemberExpression(node) {
|
||||
if (!node.optional) {
|
||||
checkUnsafeUsage(node.object);
|
||||
}
|
||||
},
|
||||
TaggedTemplateExpression(node) {
|
||||
checkUnsafeUsage(node.tag);
|
||||
},
|
||||
ForOfStatement(node) {
|
||||
checkUnsafeUsage(node.right);
|
||||
},
|
||||
SpreadElement(node) {
|
||||
if (node.parent && node.parent.type !== "ObjectExpression") {
|
||||
checkUnsafeUsage(node.argument);
|
||||
}
|
||||
},
|
||||
BinaryExpression(node) {
|
||||
if (UNSAFE_RELATIONAL_OPERATORS.has(node.operator)) {
|
||||
checkUnsafeUsage(node.right);
|
||||
}
|
||||
if (
|
||||
disallowArithmeticOperators &&
|
||||
UNSAFE_ARITHMETIC_OPERATORS.has(node.operator)
|
||||
) {
|
||||
checkUnsafeArithmetic(node.right);
|
||||
checkUnsafeArithmetic(node.left);
|
||||
}
|
||||
},
|
||||
WithStatement(node) {
|
||||
checkUnsafeUsage(node.object);
|
||||
},
|
||||
UnaryExpression(node) {
|
||||
if (
|
||||
disallowArithmeticOperators &&
|
||||
UNSAFE_ARITHMETIC_OPERATORS.has(node.operator)
|
||||
) {
|
||||
checkUnsafeArithmetic(node.argument);
|
||||
}
|
||||
},
|
||||
AssignmentExpression(node) {
|
||||
if (
|
||||
disallowArithmeticOperators &&
|
||||
UNSAFE_ASSIGNMENT_OPERATORS.has(node.operator)
|
||||
) {
|
||||
checkUnsafeArithmetic(node.right);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
13
node_modules/eslint/lib/rules/no-unused-expressions.js
generated
vendored
13
node_modules/eslint/lib/rules/no-unused-expressions.js
generated
vendored
|
|
@ -50,6 +50,10 @@ module.exports = {
|
|||
allowTaggedTemplates: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
},
|
||||
enforceForJSX: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
|
|
@ -65,7 +69,8 @@ module.exports = {
|
|||
const config = context.options[0] || {},
|
||||
allowShortCircuit = config.allowShortCircuit || false,
|
||||
allowTernary = config.allowTernary || false,
|
||||
allowTaggedTemplates = config.allowTaggedTemplates || false;
|
||||
allowTaggedTemplates = config.allowTaggedTemplates || false,
|
||||
enforceForJSX = config.enforceForJSX || false;
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-description
|
||||
/**
|
||||
|
|
@ -140,6 +145,12 @@ module.exports = {
|
|||
},
|
||||
FunctionExpression: alwaysTrue,
|
||||
Identifier: alwaysTrue,
|
||||
JSXElement() {
|
||||
return enforceForJSX;
|
||||
},
|
||||
JSXFragment() {
|
||||
return enforceForJSX;
|
||||
},
|
||||
Literal: alwaysTrue,
|
||||
LogicalExpression(node) {
|
||||
if (allowShortCircuit) {
|
||||
|
|
|
|||
91
node_modules/eslint/lib/rules/no-unused-vars.js
generated
vendored
91
node_modules/eslint/lib/rules/no-unused-vars.js
generated
vendored
|
|
@ -196,6 +196,17 @@ module.exports = {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a node is a sibling of the rest property or not.
|
||||
* @param {ASTNode} node a node to check
|
||||
* @returns {boolean} True if the node is a sibling of the rest property, otherwise false.
|
||||
*/
|
||||
function hasRestSibling(node) {
|
||||
return node.type === "Property" &&
|
||||
node.parent.type === "ObjectPattern" &&
|
||||
REST_PROPERTY_TYPE.test(node.parent.properties[node.parent.properties.length - 1].type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a variable has a sibling rest property
|
||||
* @param {Variable} variable eslint-scope variable object.
|
||||
|
|
@ -204,16 +215,10 @@ module.exports = {
|
|||
*/
|
||||
function hasRestSpreadSibling(variable) {
|
||||
if (config.ignoreRestSiblings) {
|
||||
return variable.defs.some(def => {
|
||||
const propertyNode = def.name.parent;
|
||||
const patternNode = propertyNode.parent;
|
||||
const hasRestSiblingDefinition = variable.defs.some(def => hasRestSibling(def.name.parent));
|
||||
const hasRestSiblingReference = variable.references.some(ref => hasRestSibling(ref.identifier.parent));
|
||||
|
||||
return (
|
||||
propertyNode.type === "Property" &&
|
||||
patternNode.type === "ObjectPattern" &&
|
||||
REST_PROPERTY_TYPE.test(patternNode.properties[patternNode.properties.length - 1].type)
|
||||
);
|
||||
});
|
||||
return hasRestSiblingDefinition || hasRestSiblingReference;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -405,6 +410,31 @@ module.exports = {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given node is unused expression or not.
|
||||
* @param {ASTNode} node The node itself
|
||||
* @returns {boolean} The node is an unused expression.
|
||||
* @private
|
||||
*/
|
||||
function isUnusedExpression(node) {
|
||||
const parent = node.parent;
|
||||
|
||||
if (parent.type === "ExpressionStatement") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (parent.type === "SequenceExpression") {
|
||||
const isLastExpression = parent.expressions[parent.expressions.length - 1] === node;
|
||||
|
||||
if (!isLastExpression) {
|
||||
return true;
|
||||
}
|
||||
return isUnusedExpression(parent);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given reference is a read to update itself or not.
|
||||
* @param {eslint-scope.Reference} ref A reference to check.
|
||||
|
|
@ -415,23 +445,28 @@ module.exports = {
|
|||
function isReadForItself(ref, rhsNode) {
|
||||
const id = ref.identifier;
|
||||
const parent = id.parent;
|
||||
const grandparent = parent.parent;
|
||||
|
||||
return ref.isRead() && (
|
||||
|
||||
// self update. e.g. `a += 1`, `a++`
|
||||
(// in RHS of an assignment for itself. e.g. `a = a + 1`
|
||||
((
|
||||
parent.type === "AssignmentExpression" &&
|
||||
grandparent.type === "ExpressionStatement" &&
|
||||
parent.left === id
|
||||
) ||
|
||||
(
|
||||
parent.type === "UpdateExpression" &&
|
||||
grandparent.type === "ExpressionStatement"
|
||||
) || rhsNode &&
|
||||
isInside(id, rhsNode) &&
|
||||
!isInsideOfStorableFunction(id, rhsNode)))
|
||||
(
|
||||
parent.type === "AssignmentExpression" &&
|
||||
parent.left === id &&
|
||||
isUnusedExpression(parent)
|
||||
) ||
|
||||
(
|
||||
parent.type === "UpdateExpression" &&
|
||||
isUnusedExpression(parent)
|
||||
)
|
||||
) ||
|
||||
|
||||
// in RHS of an assignment for itself. e.g. `a = a + 1`
|
||||
(
|
||||
rhsNode &&
|
||||
isInside(id, rhsNode) &&
|
||||
!isInsideOfStorableFunction(id, rhsNode)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -619,10 +654,18 @@ module.exports = {
|
|||
|
||||
// Report the first declaration.
|
||||
if (unusedVar.defs.length > 0) {
|
||||
|
||||
// report last write reference, https://github.com/eslint/eslint/issues/14324
|
||||
const writeReferences = unusedVar.references.filter(ref => ref.isWrite() && ref.from.variableScope === unusedVar.scope.variableScope);
|
||||
|
||||
let referenceToReport;
|
||||
|
||||
if (writeReferences.length > 0) {
|
||||
referenceToReport = writeReferences[writeReferences.length - 1];
|
||||
}
|
||||
|
||||
context.report({
|
||||
node: unusedVar.references.length ? unusedVar.references[
|
||||
unusedVar.references.length - 1
|
||||
].identifier : unusedVar.identifiers[0],
|
||||
node: referenceToReport ? referenceToReport.identifier : unusedVar.identifiers[0],
|
||||
messageId: "unusedVar",
|
||||
data: unusedVar.references.some(ref => ref.isWrite())
|
||||
? getAssignedMessageData(unusedVar)
|
||||
|
|
|
|||
3
node_modules/eslint/lib/rules/no-useless-backreference.js
generated
vendored
3
node_modules/eslint/lib/rules/no-useless-backreference.js
generated
vendored
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("eslint-utils");
|
||||
const { RegExpParser, visitRegExpAST } = require("regexpp");
|
||||
const lodash = require("lodash");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
|
@ -137,7 +136,7 @@ module.exports = {
|
|||
|
||||
// the opposite of the previous when the regex is matching backward in a lookbehind context.
|
||||
messageId = "backward";
|
||||
} else if (lodash.last(groupCut).type === "Alternative") {
|
||||
} else if (groupCut[groupCut.length - 1].type === "Alternative") {
|
||||
|
||||
// group's and bref's ancestor nodes below the lowest common ancestor are sibling alternatives => they're disjunctive.
|
||||
messageId = "disjunctive";
|
||||
|
|
|
|||
10
node_modules/eslint/lib/rules/no-useless-computed-key.js
generated
vendored
10
node_modules/eslint/lib/rules/no-useless-computed-key.js
generated
vendored
|
|
@ -8,7 +8,6 @@
|
|||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const lodash = require("lodash");
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -95,9 +94,16 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A no-op function to act as placeholder for checking a node when the `enforceForClassMembers` option is `false`.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function noop() {}
|
||||
|
||||
return {
|
||||
Property: check,
|
||||
MethodDefinition: enforceForClassMembers ? check : lodash.noop
|
||||
MethodDefinition: enforceForClassMembers ? check : noop
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
8
node_modules/eslint/lib/rules/no-useless-constructor.js
generated
vendored
8
node_modules/eslint/lib/rules/no-useless-constructor.js
generated
vendored
|
|
@ -162,6 +162,14 @@ module.exports = {
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent crashing on parsers which do not require class constructor
|
||||
* to have a body, e.g. typescript and flow
|
||||
*/
|
||||
if (!node.value.body) {
|
||||
return;
|
||||
}
|
||||
|
||||
const body = node.value.body.body;
|
||||
const ctorParams = node.value.params;
|
||||
const superClass = node.parent.parent.superClass;
|
||||
|
|
|
|||
8
node_modules/eslint/lib/rules/no-useless-escape.js
generated
vendored
8
node_modules/eslint/lib/rules/no-useless-escape.js
generated
vendored
|
|
@ -109,9 +109,9 @@ module.exports = {
|
|||
* @returns {void}
|
||||
*/
|
||||
function report(node, startOffset, character) {
|
||||
const start = sourceCode.getLocFromIndex(sourceCode.getIndexFromLoc(node.loc.start) + startOffset);
|
||||
const rangeStart = sourceCode.getIndexFromLoc(node.loc.start) + startOffset;
|
||||
const rangeStart = node.range[0] + startOffset;
|
||||
const range = [rangeStart, rangeStart + 1];
|
||||
const start = sourceCode.getLocFromIndex(rangeStart);
|
||||
|
||||
context.report({
|
||||
node,
|
||||
|
|
@ -172,7 +172,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
if (isUnnecessaryEscape && !isQuoteEscape) {
|
||||
report(node, match.index + 1, match[0].slice(1));
|
||||
report(node, match.index, match[0].slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -206,7 +206,7 @@ module.exports = {
|
|||
return;
|
||||
}
|
||||
|
||||
const value = isTemplateElement ? node.value.raw : node.raw.slice(1, -1);
|
||||
const value = isTemplateElement ? sourceCode.getText(node) : node.raw;
|
||||
const pattern = /\\[^\d]/gu;
|
||||
let match;
|
||||
|
||||
|
|
|
|||
44
node_modules/eslint/lib/rules/no-useless-rename.js
generated
vendored
44
node_modules/eslint/lib/rules/no-useless-rename.js
generated
vendored
|
|
@ -5,6 +5,12 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -54,11 +60,10 @@ module.exports = {
|
|||
* Reports error for unnecessarily renamed assignments
|
||||
* @param {ASTNode} node node to report
|
||||
* @param {ASTNode} initial node with initial name value
|
||||
* @param {ASTNode} result node with new name value
|
||||
* @param {string} type the type of the offending node
|
||||
* @returns {void}
|
||||
*/
|
||||
function reportError(node, initial, result, type) {
|
||||
function reportError(node, initial, type) {
|
||||
const name = initial.type === "Identifier" ? initial.name : initial.value;
|
||||
|
||||
return context.report({
|
||||
|
|
@ -69,18 +74,21 @@ module.exports = {
|
|||
type
|
||||
},
|
||||
fix(fixer) {
|
||||
if (sourceCode.commentsExistBetween(initial, result)) {
|
||||
const replacementNode = node.type === "Property" ? node.value : node.local;
|
||||
|
||||
if (sourceCode.getCommentsInside(node).length > sourceCode.getCommentsInside(replacementNode).length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const replacementText = result.type === "AssignmentPattern"
|
||||
? sourceCode.getText(result)
|
||||
: name;
|
||||
// Don't autofix code such as `({foo: (foo) = a} = obj);`, parens are not allowed in shorthand properties.
|
||||
if (
|
||||
replacementNode.type === "AssignmentPattern" &&
|
||||
astUtils.isParenthesised(sourceCode, replacementNode.left)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.replaceTextRange([
|
||||
initial.range[0],
|
||||
result.range[1]
|
||||
], replacementText);
|
||||
return fixer.replaceText(node, sourceCode.getText(replacementNode));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -97,19 +105,11 @@ module.exports = {
|
|||
|
||||
for (const property of node.properties) {
|
||||
|
||||
/*
|
||||
* TODO: Remove after babel-eslint removes ExperimentalRestProperty
|
||||
* https://github.com/eslint/eslint/issues/12335
|
||||
*/
|
||||
if (property.type === "ExperimentalRestProperty") {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties using shorthand syntax and rest elements can not be renamed.
|
||||
* If the property is computed, we have no idea if a rename is useless or not.
|
||||
*/
|
||||
if (property.shorthand || property.type === "RestElement" || property.computed) {
|
||||
if (property.type !== "Property" || property.shorthand || property.computed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ module.exports = {
|
|||
const renamedKey = property.value.type === "AssignmentPattern" ? property.value.left.name : property.value.name;
|
||||
|
||||
if (key === renamedKey) {
|
||||
reportError(property, property.key, property.value, "Destructuring assignment");
|
||||
reportError(property, property.key, "Destructuring assignment");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -134,7 +134,7 @@ module.exports = {
|
|||
|
||||
if (node.imported.name === node.local.name &&
|
||||
node.imported.range[0] !== node.local.range[0]) {
|
||||
reportError(node, node.imported, node.local, "Import");
|
||||
reportError(node, node.imported, "Import");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ module.exports = {
|
|||
|
||||
if (node.local.name === node.exported.name &&
|
||||
node.local.range[0] !== node.exported.range[0]) {
|
||||
reportError(node, node.local, node.exported, "Export");
|
||||
reportError(node, node.local, "Export");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/no-warning-comments.js
generated
vendored
2
node_modules/eslint/lib/rules/no-warning-comments.js
generated
vendored
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { escapeRegExp } = require("lodash");
|
||||
const escapeRegExp = require("escape-string-regexp");
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
const CHAR_LIMIT = 40;
|
||||
|
|
|
|||
25
node_modules/eslint/lib/rules/object-curly-newline.js
generated
vendored
25
node_modules/eslint/lib/rules/object-curly-newline.js
generated
vendored
|
|
@ -10,7 +10,6 @@
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
const lodash = require("lodash");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
|
@ -69,6 +68,24 @@ function normalizeOptionValue(value) {
|
|||
return { multiline, minProperties, consistent };
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a value is an object.
|
||||
* @param {any} value The value to check
|
||||
* @returns {boolean} `true` if the value is an object, otherwise `false`
|
||||
*/
|
||||
function isObject(value) {
|
||||
return typeof value === "object" && value !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an option is a node-specific option
|
||||
* @param {any} option The option to check
|
||||
* @returns {boolean} `true` if the option is node-specific, otherwise `false`
|
||||
*/
|
||||
function isNodeSpecificOption(option) {
|
||||
return isObject(option) || typeof option === "string";
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a given option value.
|
||||
* @param {string|Object|undefined} options An option value to parse.
|
||||
|
|
@ -80,9 +97,7 @@ function normalizeOptionValue(value) {
|
|||
* }} Normalized option object.
|
||||
*/
|
||||
function normalizeOptions(options) {
|
||||
const isNodeSpecificOption = lodash.overSome([lodash.isPlainObject, lodash.isString]);
|
||||
|
||||
if (lodash.isPlainObject(options) && lodash.some(options, isNodeSpecificOption)) {
|
||||
if (isObject(options) && Object.values(options).some(isNodeSpecificOption)) {
|
||||
return {
|
||||
ObjectExpression: normalizeOptionValue(options.ObjectExpression),
|
||||
ObjectPattern: normalizeOptionValue(options.ObjectPattern),
|
||||
|
|
@ -134,7 +149,7 @@ module.exports = {
|
|||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "enforce consistent line breaks inside braces",
|
||||
description: "enforce consistent line breaks after opening and before closing braces",
|
||||
category: "Stylistic Issues",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/object-curly-newline"
|
||||
|
|
|
|||
42
node_modules/eslint/lib/rules/one-var.js
generated
vendored
42
node_modules/eslint/lib/rules/one-var.js
generated
vendored
|
|
@ -5,6 +5,25 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines whether the given node is in a statement list.
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {boolean} `true` if the given node is in a statement list
|
||||
*/
|
||||
function isInStatementList(node) {
|
||||
return astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -268,8 +287,8 @@ module.exports = {
|
|||
|
||||
/**
|
||||
* Fixer to join VariableDeclaration's into a single declaration
|
||||
* @param {VariableDeclarator[]} declarations The `VariableDeclaration` to join
|
||||
* @returns {Function} The fixer function
|
||||
* @param {VariableDeclarator[]} declarations The `VariableDeclaration` to join
|
||||
* @returns {Function} The fixer function
|
||||
*/
|
||||
function joinDeclarations(declarations) {
|
||||
const declaration = declarations[0];
|
||||
|
|
@ -297,10 +316,17 @@ module.exports = {
|
|||
|
||||
/**
|
||||
* Fixer to split a VariableDeclaration into individual declarations
|
||||
* @param {VariableDeclaration} declaration The `VariableDeclaration` to split
|
||||
* @returns {Function} The fixer function
|
||||
* @param {VariableDeclaration} declaration The `VariableDeclaration` to split
|
||||
* @returns {Function|null} The fixer function
|
||||
*/
|
||||
function splitDeclarations(declaration) {
|
||||
const { parent } = declaration;
|
||||
|
||||
// don't autofix code such as: if (foo) var x, y;
|
||||
if (!isInStatementList(parent.type === "ExportNamedDeclaration" ? parent : declaration)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer => declaration.declarations.map(declarator => {
|
||||
const tokenAfterDeclarator = sourceCode.getTokenAfter(declarator);
|
||||
|
||||
|
|
@ -314,12 +340,14 @@ module.exports = {
|
|||
return null;
|
||||
}
|
||||
|
||||
const exportPlacement = declaration.parent.type === "ExportNamedDeclaration" ? "export " : "";
|
||||
|
||||
/*
|
||||
* `var x,y`
|
||||
* tokenAfterDeclarator ^^ afterComma
|
||||
*/
|
||||
if (afterComma.range[0] === tokenAfterDeclarator.range[1]) {
|
||||
return fixer.replaceText(tokenAfterDeclarator, `; ${declaration.kind} `);
|
||||
return fixer.replaceText(tokenAfterDeclarator, `; ${exportPlacement}${declaration.kind} `);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -341,11 +369,11 @@ module.exports = {
|
|||
|
||||
return fixer.replaceTextRange(
|
||||
[tokenAfterDeclarator.range[0], lastComment.range[0]],
|
||||
`;${sourceCode.text.slice(tokenAfterDeclarator.range[1], lastComment.range[0])}${declaration.kind} `
|
||||
`;${sourceCode.text.slice(tokenAfterDeclarator.range[1], lastComment.range[0])}${exportPlacement}${declaration.kind} `
|
||||
);
|
||||
}
|
||||
|
||||
return fixer.replaceText(tokenAfterDeclarator, `; ${declaration.kind}`);
|
||||
return fixer.replaceText(tokenAfterDeclarator, `; ${exportPlacement}${declaration.kind}`);
|
||||
}).filter(x => x);
|
||||
}
|
||||
|
||||
|
|
|
|||
9
node_modules/eslint/lib/rules/operator-assignment.js
generated
vendored
9
node_modules/eslint/lib/rules/operator-assignment.js
generated
vendored
|
|
@ -76,8 +76,8 @@ module.exports = {
|
|||
|
||||
fixable: "code",
|
||||
messages: {
|
||||
replaced: "Assignment can be replaced with operator assignment.",
|
||||
unexpected: "Unexpected operator assignment shorthand."
|
||||
replaced: "Assignment (=) can be replaced with operator assignment ({{operator}}=).",
|
||||
unexpected: "Unexpected operator assignment ({{operator}}=) shorthand."
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -113,6 +113,7 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
messageId: "replaced",
|
||||
data: { operator },
|
||||
fix(fixer) {
|
||||
if (canBeFixed(left) && canBeFixed(expr.left)) {
|
||||
const equalsToken = getOperatorToken(node);
|
||||
|
|
@ -139,7 +140,8 @@ module.exports = {
|
|||
*/
|
||||
context.report({
|
||||
node,
|
||||
messageId: "replaced"
|
||||
messageId: "replaced",
|
||||
data: { operator }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -155,6 +157,7 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
messageId: "unexpected",
|
||||
data: { operator: node.operator },
|
||||
fix(fixer) {
|
||||
if (canBeFixed(node.left)) {
|
||||
const firstToken = sourceCode.getFirstToken(node);
|
||||
|
|
|
|||
8
node_modules/eslint/lib/rules/prefer-arrow-callback.js
generated
vendored
8
node_modules/eslint/lib/rules/prefer-arrow-callback.js
generated
vendored
|
|
@ -295,7 +295,7 @@ module.exports = {
|
|||
* If the callback function has duplicates in its list of parameters (possible in sloppy mode),
|
||||
* don't replace it with an arrow function, because this is a SyntaxError with arrow functions.
|
||||
*/
|
||||
return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove `.bind(this)` if exists.
|
||||
|
|
@ -307,7 +307,7 @@ module.exports = {
|
|||
* E.g. `(foo || function(){}).bind(this)`
|
||||
*/
|
||||
if (memberNode.type !== "MemberExpression") {
|
||||
return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
|
||||
return;
|
||||
}
|
||||
|
||||
const callNode = memberNode.parent;
|
||||
|
|
@ -320,12 +320,12 @@ module.exports = {
|
|||
* ^^^^^^^^^^^^
|
||||
*/
|
||||
if (astUtils.isParenthesised(sourceCode, memberNode)) {
|
||||
return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
|
||||
return;
|
||||
}
|
||||
|
||||
// If comments exist in the `.bind(this)`, don't remove those.
|
||||
if (sourceCode.commentsExistBetween(firstTokenToRemove, lastTokenToRemove)) {
|
||||
return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
|
||||
return;
|
||||
}
|
||||
|
||||
yield fixer.removeRange([firstTokenToRemove.range[0], lastTokenToRemove.range[1]]);
|
||||
|
|
|
|||
21
node_modules/eslint/lib/rules/prefer-const.js
generated
vendored
21
node_modules/eslint/lib/rules/prefer-const.js
generated
vendored
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const FixTracker = require("./utils/fix-tracker");
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -451,10 +456,18 @@ module.exports = {
|
|||
messageId: "useConst",
|
||||
data: node,
|
||||
fix: shouldFix
|
||||
? fixer => fixer.replaceText(
|
||||
sourceCode.getFirstToken(varDeclParent, t => t.value === varDeclParent.kind),
|
||||
"const"
|
||||
)
|
||||
? fixer => {
|
||||
const letKeywordToken = sourceCode.getFirstToken(varDeclParent, t => t.value === varDeclParent.kind);
|
||||
|
||||
/**
|
||||
* Extend the replacement range to the whole declaration,
|
||||
* in order to prevent other fixes in the same pass
|
||||
* https://github.com/eslint/eslint/issues/13899
|
||||
*/
|
||||
return new FixTracker(fixer, sourceCode)
|
||||
.retainRange(varDeclParent.range)
|
||||
.replaceTextRange(letKeywordToken.range, "const");
|
||||
}
|
||||
: null
|
||||
});
|
||||
});
|
||||
|
|
|
|||
28
node_modules/eslint/lib/rules/prefer-destructuring.js
generated
vendored
28
node_modules/eslint/lib/rules/prefer-destructuring.js
generated
vendored
|
|
@ -4,6 +4,18 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const PRECEDENCE_OF_ASSIGNMENT_EXPR = astUtils.getPrecedence({ type: "AssignmentExpression" });
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -156,13 +168,15 @@ module.exports = {
|
|||
* Assignment expression is not fixed.
|
||||
* Array destructuring is not fixed.
|
||||
* Renamed property is not fixed.
|
||||
* @param {ASTNode} node the the node to evaluate
|
||||
* @param {ASTNode} node the node to evaluate
|
||||
* @returns {boolean} whether or not the node should be fixed
|
||||
*/
|
||||
function shouldFix(node) {
|
||||
return node.type === "VariableDeclarator" &&
|
||||
node.id.type === "Identifier" &&
|
||||
node.init.type === "MemberExpression" &&
|
||||
!node.init.computed &&
|
||||
node.init.property.type === "Identifier" &&
|
||||
node.id.name === node.init.property.name;
|
||||
}
|
||||
|
||||
|
|
@ -183,9 +197,15 @@ module.exports = {
|
|||
return null;
|
||||
}
|
||||
|
||||
let objectText = sourceCode.getText(rightNode.object);
|
||||
|
||||
if (astUtils.getPrecedence(rightNode.object) < PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
||||
objectText = `(${objectText})`;
|
||||
}
|
||||
|
||||
return fixer.replaceText(
|
||||
node,
|
||||
`{${rightNode.property.name}} = ${sourceCode.getText(rightNode.object)}`
|
||||
`{${rightNode.property.name}} = ${objectText}`
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +279,7 @@ module.exports = {
|
|||
* @param {ASTNode} node the AssignmentExpression node
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkAssigmentExpression(node) {
|
||||
function checkAssignmentExpression(node) {
|
||||
if (node.operator === "=") {
|
||||
performCheck(node.left, node.right, node);
|
||||
}
|
||||
|
|
@ -271,7 +291,7 @@ module.exports = {
|
|||
|
||||
return {
|
||||
VariableDeclarator: checkVariableDeclarator,
|
||||
AssignmentExpression: checkAssigmentExpression
|
||||
AssignmentExpression: checkAssignmentExpression
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
1
node_modules/eslint/lib/rules/prefer-exponentiation-operator.js
generated
vendored
1
node_modules/eslint/lib/rules/prefer-exponentiation-operator.js
generated
vendored
|
|
@ -30,6 +30,7 @@ function doesBaseNeedParens(base) {
|
|||
astUtils.getPrecedence(base) <= PRECEDENCE_OF_EXPONENTIATION_EXPR ||
|
||||
|
||||
// An unary operator cannot be used immediately before an exponentiation expression
|
||||
base.type === "AwaitExpression" ||
|
||||
base.type === "UnaryExpression"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/prefer-reflect.js
generated
vendored
4
node_modules/eslint/lib/rules/prefer-reflect.js
generated
vendored
|
|
@ -105,10 +105,10 @@ module.exports = {
|
|||
CallExpression(node) {
|
||||
const methodName = (node.callee.property || {}).name;
|
||||
const isReflectCall = (node.callee.object || {}).name === "Reflect";
|
||||
const hasReflectSubsitute = Object.prototype.hasOwnProperty.call(reflectSubstitutes, methodName);
|
||||
const hasReflectSubstitute = Object.prototype.hasOwnProperty.call(reflectSubstitutes, methodName);
|
||||
const userConfiguredException = exceptions.indexOf(methodName) !== -1;
|
||||
|
||||
if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) {
|
||||
if (hasReflectSubstitute && !isReflectCall && !userConfiguredException) {
|
||||
report(node, existingNames[methodName], reflectSubstitutes[methodName]);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
38
node_modules/eslint/lib/rules/prefer-template.js
generated
vendored
38
node_modules/eslint/lib/rules/prefer-template.js
generated
vendored
|
|
@ -39,33 +39,25 @@ function getTopConcatBinaryExpression(node) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines whether a given node is a octal escape sequence
|
||||
* Checks whether or not a node contains a string literal with an octal or non-octal decimal escape sequence
|
||||
* @param {ASTNode} node A node to check
|
||||
* @returns {boolean} `true` if the node is an octal escape sequence
|
||||
* @returns {boolean} `true` if at least one string literal within the node contains
|
||||
* an octal or non-octal decimal escape sequence
|
||||
*/
|
||||
function isOctalEscapeSequence(node) {
|
||||
|
||||
// No need to check TemplateLiterals – would throw error with octal escape
|
||||
const isStringLiteral = node.type === "Literal" && typeof node.value === "string";
|
||||
|
||||
if (!isStringLiteral) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return astUtils.hasOctalEscapeSequence(node.raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not a node contains a octal escape sequence
|
||||
* @param {ASTNode} node A node to check
|
||||
* @returns {boolean} `true` if the node contains an octal escape sequence
|
||||
*/
|
||||
function hasOctalEscapeSequence(node) {
|
||||
function hasOctalOrNonOctalDecimalEscapeSequence(node) {
|
||||
if (isConcatenation(node)) {
|
||||
return hasOctalEscapeSequence(node.left) || hasOctalEscapeSequence(node.right);
|
||||
return (
|
||||
hasOctalOrNonOctalDecimalEscapeSequence(node.left) ||
|
||||
hasOctalOrNonOctalDecimalEscapeSequence(node.right)
|
||||
);
|
||||
}
|
||||
|
||||
return isOctalEscapeSequence(node);
|
||||
// No need to check TemplateLiterals – would throw parsing error
|
||||
if (node.type === "Literal" && typeof node.value === "string") {
|
||||
return astUtils.hasOctalOrNonOctalDecimalEscapeSequence(node.raw);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -237,7 +229,7 @@ module.exports = {
|
|||
function fixNonStringBinaryExpression(fixer, node) {
|
||||
const topBinaryExpr = getTopConcatBinaryExpression(node.parent);
|
||||
|
||||
if (hasOctalEscapeSequence(topBinaryExpr)) {
|
||||
if (hasOctalOrNonOctalDecimalEscapeSequence(topBinaryExpr)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
7
node_modules/eslint/lib/rules/quotes.js
generated
vendored
7
node_modules/eslint/lib/rules/quotes.js
generated
vendored
|
|
@ -282,9 +282,12 @@ module.exports = {
|
|||
description: settings.description
|
||||
},
|
||||
fix(fixer) {
|
||||
if (quoteOption === "backtick" && astUtils.hasOctalEscapeSequence(rawVal)) {
|
||||
if (quoteOption === "backtick" && astUtils.hasOctalOrNonOctalDecimalEscapeSequence(rawVal)) {
|
||||
|
||||
// An octal escape sequence in a template literal would produce syntax error, even in non-strict mode.
|
||||
/*
|
||||
* An octal or non-octal decimal escape sequence in a template literal would
|
||||
* produce syntax error, even in non-strict mode.
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
22
node_modules/eslint/lib/rules/radix.js
generated
vendored
22
node_modules/eslint/lib/rules/radix.js
generated
vendored
|
|
@ -82,7 +82,8 @@ module.exports = {
|
|||
description: "enforce the consistent use of the radix argument when using `parseInt()`",
|
||||
category: "Best Practices",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/rules/radix"
|
||||
url: "https://eslint.org/docs/rules/radix",
|
||||
suggestion: true
|
||||
},
|
||||
|
||||
schema: [
|
||||
|
|
@ -95,7 +96,8 @@ module.exports = {
|
|||
missingParameters: "Missing parameters.",
|
||||
redundantRadix: "Redundant radix parameter.",
|
||||
missingRadix: "Missing radix parameter.",
|
||||
invalidRadix: "Invalid radix parameter, must be an integer between 2 and 36."
|
||||
invalidRadix: "Invalid radix parameter, must be an integer between 2 and 36.",
|
||||
addRadixParameter10: "Add radix parameter `10` for parsing decimal numbers."
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -123,7 +125,21 @@ module.exports = {
|
|||
if (mode === MODE_ALWAYS) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "missingRadix"
|
||||
messageId: "missingRadix",
|
||||
suggest: [
|
||||
{
|
||||
messageId: "addRadixParameter10",
|
||||
fix(fixer) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
const tokens = sourceCode.getTokens(node);
|
||||
const lastToken = tokens[tokens.length - 1]; // Parenthesis.
|
||||
const secondToLastToken = tokens[tokens.length - 2]; // May or may not be a comma.
|
||||
const hasTrailingComma = secondToLastToken.type === "Punctuator" && secondToLastToken.value === ",";
|
||||
|
||||
return fixer.insertTextBefore(lastToken, hasTrailingComma ? " 10," : ", 10");
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
44
node_modules/eslint/lib/rules/require-atomic-updates.js
generated
vendored
44
node_modules/eslint/lib/rules/require-atomic-updates.js
generated
vendored
|
|
@ -13,6 +13,10 @@
|
|||
*/
|
||||
function createReferenceMap(scope, outReferenceMap = new Map()) {
|
||||
for (const reference of scope.references) {
|
||||
if (reference.resolved === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
outReferenceMap.set(reference.identifier, reference);
|
||||
}
|
||||
for (const childScope of scope.childScopes) {
|
||||
|
|
@ -86,39 +90,42 @@ class SegmentInfo {
|
|||
* @returns {void}
|
||||
*/
|
||||
initialize(segment) {
|
||||
const outdatedReadVariableNames = new Set();
|
||||
const freshReadVariableNames = new Set();
|
||||
const outdatedReadVariables = new Set();
|
||||
const freshReadVariables = new Set();
|
||||
|
||||
for (const prevSegment of segment.prevSegments) {
|
||||
const info = this.info.get(prevSegment);
|
||||
|
||||
if (info) {
|
||||
info.outdatedReadVariableNames.forEach(Set.prototype.add, outdatedReadVariableNames);
|
||||
info.freshReadVariableNames.forEach(Set.prototype.add, freshReadVariableNames);
|
||||
info.outdatedReadVariables.forEach(Set.prototype.add, outdatedReadVariables);
|
||||
info.freshReadVariables.forEach(Set.prototype.add, freshReadVariables);
|
||||
}
|
||||
}
|
||||
|
||||
this.info.set(segment, { outdatedReadVariableNames, freshReadVariableNames });
|
||||
this.info.set(segment, { outdatedReadVariables, freshReadVariables });
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a given variable as read on given segments.
|
||||
* @param {PathSegment[]} segments The segments that it read the variable on.
|
||||
* @param {string} variableName The variable name to be read.
|
||||
* @param {Variable} variable The variable to be read.
|
||||
* @returns {void}
|
||||
*/
|
||||
markAsRead(segments, variableName) {
|
||||
markAsRead(segments, variable) {
|
||||
for (const segment of segments) {
|
||||
const info = this.info.get(segment);
|
||||
|
||||
if (info) {
|
||||
info.freshReadVariableNames.add(variableName);
|
||||
info.freshReadVariables.add(variable);
|
||||
|
||||
// If a variable is freshly read again, then it's no more out-dated.
|
||||
info.outdatedReadVariables.delete(variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move `freshReadVariableNames` to `outdatedReadVariableNames`.
|
||||
* Move `freshReadVariables` to `outdatedReadVariables`.
|
||||
* @param {PathSegment[]} segments The segments to process.
|
||||
* @returns {void}
|
||||
*/
|
||||
|
|
@ -127,8 +134,8 @@ class SegmentInfo {
|
|||
const info = this.info.get(segment);
|
||||
|
||||
if (info) {
|
||||
info.freshReadVariableNames.forEach(Set.prototype.add, info.outdatedReadVariableNames);
|
||||
info.freshReadVariableNames.clear();
|
||||
info.freshReadVariables.forEach(Set.prototype.add, info.outdatedReadVariables);
|
||||
info.freshReadVariables.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -136,14 +143,14 @@ class SegmentInfo {
|
|||
/**
|
||||
* Check if a given variable is outdated on the current segments.
|
||||
* @param {PathSegment[]} segments The current segments.
|
||||
* @param {string} variableName The variable name to check.
|
||||
* @param {Variable} variable The variable to check.
|
||||
* @returns {boolean} `true` if the variable is outdated on the segments.
|
||||
*/
|
||||
isOutdated(segments, variableName) {
|
||||
isOutdated(segments, variable) {
|
||||
for (const segment of segments) {
|
||||
const info = this.info.get(segment);
|
||||
|
||||
if (info && info.outdatedReadVariableNames.has(variableName)) {
|
||||
if (info && info.outdatedReadVariables.has(variable)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -211,14 +218,13 @@ module.exports = {
|
|||
if (!reference) {
|
||||
return;
|
||||
}
|
||||
const name = reference.identifier.name;
|
||||
const variable = reference.resolved;
|
||||
const writeExpr = getWriteExpr(reference);
|
||||
const isMemberAccess = reference.identifier.parent.type === "MemberExpression";
|
||||
|
||||
// Add a fresh read variable.
|
||||
if (reference.isRead() && !(writeExpr && writeExpr.parent.operator === "=")) {
|
||||
segmentInfo.markAsRead(codePath.currentSegments, name);
|
||||
segmentInfo.markAsRead(codePath.currentSegments, variable);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -242,7 +248,7 @@ module.exports = {
|
|||
|
||||
/*
|
||||
* Verify assignments.
|
||||
* If the reference exists in `outdatedReadVariableNames` list, report it.
|
||||
* If the reference exists in `outdatedReadVariables` list, report it.
|
||||
*/
|
||||
":expression:exit"(node) {
|
||||
const { codePath, referenceMap } = stack;
|
||||
|
|
@ -264,9 +270,9 @@ module.exports = {
|
|||
assignmentReferences.delete(node);
|
||||
|
||||
for (const reference of references) {
|
||||
const name = reference.identifier.name;
|
||||
const variable = reference.resolved;
|
||||
|
||||
if (segmentInfo.isOutdated(codePath.currentSegments, name)) {
|
||||
if (segmentInfo.isOutdated(codePath.currentSegments, variable)) {
|
||||
context.report({
|
||||
node: node.parent,
|
||||
messageId: "nonAtomicUpdate",
|
||||
|
|
|
|||
43
node_modules/eslint/lib/rules/space-before-blocks.js
generated
vendored
43
node_modules/eslint/lib/rules/space-before-blocks.js
generated
vendored
|
|
@ -5,8 +5,31 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks whether the given node represents the body of a function.
|
||||
* @param {ASTNode} node the node to check.
|
||||
* @returns {boolean} `true` if the node is function body.
|
||||
*/
|
||||
function isFunctionBody(node) {
|
||||
const parent = node.parent;
|
||||
|
||||
return (
|
||||
node.type === "BlockStatement" &&
|
||||
astUtils.isFunction(parent) &&
|
||||
parent.body === node
|
||||
);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -82,13 +105,16 @@ module.exports = {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not a given token is an arrow operator (=>) or a keyword
|
||||
* in order to avoid to conflict with `arrow-spacing` and `keyword-spacing`.
|
||||
* @param {Token} token A token to check.
|
||||
* @returns {boolean} `true` if the token is an arrow operator.
|
||||
* Checks whether the spacing before the given block is already controlled by another rule:
|
||||
* - `arrow-spacing` checks spaces after `=>`.
|
||||
* - `keyword-spacing` checks spaces after keywords in certain contexts.
|
||||
* @param {Token} precedingToken first token before the block.
|
||||
* @param {ASTNode|Token} node `BlockStatement` node or `{` token of a `SwitchStatement` node.
|
||||
* @returns {boolean} `true` if requiring or disallowing spaces before the given block could produce conflicts with other rules.
|
||||
*/
|
||||
function isConflicted(token) {
|
||||
return (token.type === "Punctuator" && token.value === "=>") || token.type === "Keyword";
|
||||
function isConflicted(precedingToken, node) {
|
||||
return astUtils.isArrowToken(precedingToken) ||
|
||||
astUtils.isKeywordToken(precedingToken) && !isFunctionBody(node);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -99,13 +125,12 @@ module.exports = {
|
|||
function checkPrecedingSpace(node) {
|
||||
const precedingToken = sourceCode.getTokenBefore(node);
|
||||
|
||||
if (precedingToken && !isConflicted(precedingToken) && astUtils.isTokenOnSameLine(precedingToken, node)) {
|
||||
if (precedingToken && !isConflicted(precedingToken, node) && astUtils.isTokenOnSameLine(precedingToken, node)) {
|
||||
const hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node);
|
||||
const parent = context.getAncestors().pop();
|
||||
let requireSpace;
|
||||
let requireNoSpace;
|
||||
|
||||
if (parent.type === "FunctionExpression" || parent.type === "FunctionDeclaration") {
|
||||
if (isFunctionBody(node)) {
|
||||
requireSpace = alwaysFunctions;
|
||||
requireNoSpace = neverFunctions;
|
||||
} else if (node.type === "ClassBody") {
|
||||
|
|
|
|||
4
node_modules/eslint/lib/rules/space-infix-ops.js
generated
vendored
4
node_modules/eslint/lib/rules/space-infix-ops.js
generated
vendored
|
|
@ -132,7 +132,9 @@ module.exports = {
|
|||
|
||||
if (nonSpacedConsequentNode) {
|
||||
report(node, nonSpacedConsequentNode);
|
||||
} else if (nonSpacedAlternateNode) {
|
||||
}
|
||||
|
||||
if (nonSpacedAlternateNode) {
|
||||
report(node, nonSpacedAlternateNode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
node_modules/eslint/lib/rules/space-unary-ops.js
generated
vendored
2
node_modules/eslint/lib/rules/space-unary-ops.js
generated
vendored
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* @fileoverview This rule shoud require or disallow spaces before or after unary operations.
|
||||
* @fileoverview This rule should require or disallow spaces before or after unary operations.
|
||||
* @author Marcin Kumorek
|
||||
*/
|
||||
"use strict";
|
||||
|
|
|
|||
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