tools: update ESLint to 8.4.0

PR-URL: https://github.com/nodejs/node/pull/41085
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Derek Lewis <DerekNonGeneric@inf.is>
This commit is contained in:
Luigi Pinca authored and GitHub committed 2021-12-06 06:56:36 +00:00
1 parent b323cec78f
commit 42b51afb75
1103 files changed
+2070 -939

No files matched your search

+144
View File
@@ -0,0 +1,144 @@
/**
* @fileoverview Globals for ecmaVersion/sourceType
* @author Nicholas C. Zakas
*/
"use strict";
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
const commonjs = {
exports: true,
global: false,
module: false,
require: false
};
const es3 = {
Array: false,
Boolean: false,
constructor: false,
Date: false,
decodeURI: false,
decodeURIComponent: false,
encodeURI: false,
encodeURIComponent: false,
Error: false,
escape: false,
eval: false,
EvalError: false,
Function: false,
hasOwnProperty: false,
Infinity: false,
isFinite: false,
isNaN: false,
isPrototypeOf: false,
Math: false,
NaN: false,
Number: false,
Object: false,
parseFloat: false,
parseInt: false,
propertyIsEnumerable: false,
RangeError: false,
ReferenceError: false,
RegExp: false,
String: false,
SyntaxError: false,
toLocaleString: false,
toString: false,
TypeError: false,
undefined: false,
unescape: false,
URIError: false,
valueOf: false
};
const es5 = {
...es3,
JSON: false
};
const es2015 = {
...es5,
ArrayBuffer: false,
DataView: false,
Float32Array: false,
Float64Array: false,
Int16Array: false,
Int32Array: false,
Int8Array: false,
Map: false,
Promise: false,
Proxy: false,
Reflect: false,
Set: false,
Symbol: false,
Uint16Array: false,
Uint32Array: false,
Uint8Array: false,
Uint8ClampedArray: false,
WeakMap: false,
WeakSet: false
};
// no new globals in ES2016
const es2016 = {
...es2015
};
const es2017 = {
...es2016,
Atomics: false,
SharedArrayBuffer: false
};
// no new globals in ES2018
const es2018 = {
...es2017
};
// no new globals in ES2019
const es2019 = {
...es2018
};
const es2020 = {
...es2019,
BigInt: false,
BigInt64Array: false,
BigUint64Array: false,
globalThis: false
};
const es2021 = {
...es2020,
AggregateError: false,
FinalizationRegistry: false,
WeakRef: false
};
const es2022 = {
...es2021
};
//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------
module.exports = {
commonjs,
es3,
es5,
es2015,
es2016,
es2017,
es2018,
es2019,
es2020,
es2021,
es2022
};
+1 -1
View File
@@ -178,7 +178,7 @@ async function printResults(engine, results, format, outputFile) {
return false;
}
const output = formatter.format(results);
const output = await formatter.format(results);
if (output) {
if (outputFile) {
+11 -2
View File
@@ -26,7 +26,7 @@ exports.defaultConfig = [
/*
* Because we try to delay loading rules until absolutely
* necessary, a proxy allows us to hook into the lazy-loading
* necessary, a proxy allows us to hook into the lazy-loading
* aspect of the rules map while still keeping all of the
* relevant configuration inside of the config array.
*/
@@ -46,7 +46,16 @@ exports.defaultConfig = [
".git/**"
],
languageOptions: {
parser: "@/espree"
ecmaVersion: "latest",
sourceType: "module",
parser: "@/espree",
parserOptions: {}
}
},
{
files: ["**/*.cjs"],
languageOptions: {
sourceType: "commonjs"
}
}
];
+2 -2
View File
@@ -52,13 +52,13 @@ class FlatConfigArray extends ConfigArray {
* @param {{basePath: string, baseConfig: FlatConfig}} options The options
* to use for the config array instance.
*/
constructor(configs, { basePath, baseConfig = defaultConfig }) {
constructor(configs, { basePath, baseConfig = defaultConfig } = {}) {
super(configs, {
basePath,
schema: flatConfigSchema
});
this.unshift(baseConfig);
this.unshift(...baseConfig);
}
/* eslint-disable class-methods-use-this -- Desired as instance method */
+67
View File
@@ -0,0 +1,67 @@
/**
* @fileoverview Shared functions to work with configs.
* @author Nicholas C. Zakas
*/
"use strict";
//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------
/**
* Parses a ruleId into its plugin and rule parts.
* @param {string} ruleId The rule ID to parse.
* @returns {{pluginName:string,ruleName:string}} The plugin and rule
* parts of the ruleId;
*/
function parseRuleId(ruleId) {
let pluginName, ruleName;
// distinguish between core rules and plugin rules
if (ruleId.includes("/")) {
pluginName = ruleId.slice(0, ruleId.lastIndexOf("/"));
ruleName = ruleId.slice(pluginName.length + 1);
} else {
pluginName = "@";
ruleName = ruleId;
}
return {
pluginName,
ruleName
};
}
/**
* Retrieves a rule instance from a given config based on the ruleId.
* @param {string} ruleId The rule ID to look for.
* @param {FlatConfig} config The config to search.
* @returns {import("../shared/types").Rule|undefined} The rule if found
* or undefined if not.
*/
function getRuleFromConfig(ruleId, config) {
const { pluginName, ruleName } = parseRuleId(ruleId);
const plugin = config.plugins && config.plugins[pluginName];
let rule = plugin && plugin.rules && plugin.rules[ruleName];
// normalize function rules into objects
if (rule && typeof rule === "function") {
rule = {
create: rule
};
}
return rule;
}
//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------
module.exports = {
parseRuleId,
getRuleFromConfig
};
+13 -8
View File
@@ -195,13 +195,6 @@ function assertIsObjectOrString(value) {
// Low-Level Schemas
//-----------------------------------------------------------------------------
/** @type {ObjectPropertySchema} */
const numberSchema = {
merge: "replace",
validate: "number"
};
/** @type {ObjectPropertySchema} */
const booleanSchema = {
merge: "replace",
@@ -415,6 +408,18 @@ const rulesSchema = {
}
};
/** @type {ObjectPropertySchema} */
const ecmaVersionSchema = {
merge: "replace",
validate(value) {
if (typeof value === "number" || value === "latest") {
return;
}
throw new TypeError("Expected a number or \"latest\".");
}
};
/** @type {ObjectPropertySchema} */
const sourceTypeSchema = {
merge: "replace",
@@ -439,7 +444,7 @@ exports.flatConfigSchema = {
},
languageOptions: {
schema: {
ecmaVersion: numberSchema,
ecmaVersion: ecmaVersionSchema,
sourceType: sourceTypeSchema,
globals: globalsSchema,
parser: parserSchema,
+27 -26
View File
@@ -10,52 +10,49 @@
//-----------------------------------------------------------------------------
const ajv = require("../shared/ajv")();
const { parseRuleId, getRuleFromConfig } = require("./flat-config-helpers");
const ruleReplacements = require("../../conf/replacements.json");
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
/**
* Finds a rule with the given ID in the given config.
* @param {string} ruleId The ID of the rule to find.
* Throws a helpful error when a rule cannot be found.
* @param {Object} ruleId The rule identifier.
* @param {string} ruleId.pluginName The ID of the rule to find.
* @param {string} ruleId.ruleName The ID of the rule to find.
* @param {Object} config The config to search in.
* @throws {TypeError} For missing plugin or rule.
* @returns {{create: Function, schema: (Array|null)}} THe rule object.
* @returns {void}
*/
function findRuleDefinition(ruleId, config) {
const ruleIdParts = ruleId.split("/");
let pluginName, ruleName;
function throwRuleNotFoundError({ pluginName, ruleName }, config) {
// built-in rule
if (ruleIdParts.length === 1) {
pluginName = "@";
ruleName = ruleIdParts[0];
} else {
ruleName = ruleIdParts.pop();
pluginName = ruleIdParts.join("/");
}
const ruleId = pluginName === "@" ? ruleName : `${pluginName}/${ruleName}`;
const errorMessageHeader = `Key "rules": Key "${ruleId}"`;
let errorMessage = `${errorMessageHeader}: Could not find plugin "${pluginName}".`;
// if the plugin exists then we need to check if the rule exists
if (config.plugins && config.plugins[pluginName]) {
const replacementRuleName = ruleReplacements.rules[ruleName];
const plugin = config.plugins[pluginName];
if (pluginName === "@" && replacementRuleName) {
// first check for exact rule match
if (plugin.rules && plugin.rules[ruleName]) {
return config.plugins[pluginName].rules[ruleName];
}
errorMessage = `${errorMessageHeader}: Rule "${ruleName}" was removed and replaced by "${replacementRuleName}".`;
errorMessage = `${errorMessageHeader}: Could not find "${ruleName}" in plugin "${pluginName}".`;
} else {
// otherwise, let's see if we can find the rule name elsewhere
for (const [otherPluginName, otherPlugin] of Object.entries(config.plugins)) {
if (otherPlugin.rules && otherPlugin.rules[ruleName]) {
errorMessage += ` Did you mean "${otherPluginName}/${ruleName}"?`;
break;
errorMessage = `${errorMessageHeader}: Could not find "${ruleName}" in plugin "${pluginName}".`;
// otherwise, let's see if we can find the rule name elsewhere
for (const [otherPluginName, otherPlugin] of Object.entries(config.plugins)) {
if (otherPlugin.rules && otherPlugin.rules[ruleName]) {
errorMessage += ` Did you mean "${otherPluginName}/${ruleName}"?`;
break;
}
}
}
// falls through to throw error
@@ -154,7 +151,11 @@ class RuleValidator {
continue;
}
const rule = findRuleDefinition(ruleId, config);
const rule = getRuleFromConfig(ruleId, config);
if (!rule) {
throwRuleNotFoundError(parseRuleId(ruleId), config);
}
// Precompile and cache validator the first time
if (!this.validators.has(rule)) {
+11 -3
View File
@@ -34,7 +34,12 @@ const { version } = require("../../package.json");
/** @typedef {import("../shared/types").LintMessage} LintMessage */
/** @typedef {import("../shared/types").Plugin} Plugin */
/** @typedef {import("../shared/types").Rule} Rule */
/** @typedef {import("./load-formatter").Formatter} Formatter */
/**
* The main formatter object.
* @typedef Formatter
* @property {function(LintResult[]): string | Promise<string>} format format function.
*/
/**
* The options with which to configure the ESLint instance.
@@ -617,7 +622,7 @@ class ESLint {
throw new Error("'name' must be a string");
}
const { cliEngine } = privateMembersMap.get(this);
const { cliEngine, options } = privateMembersMap.get(this);
const formatter = cliEngine.getFormatter(name);
if (typeof formatter !== "function") {
@@ -629,7 +634,7 @@ class ESLint {
/**
* The main formatter method.
* @param {LintResults[]} results The lint results to format.
* @returns {string} The formatted lint results.
* @returns {string | Promise<string>} The formatted lint results.
*/
format(results) {
let rulesMeta = null;
@@ -637,6 +642,9 @@ class ESLint {
results.sort(compareResultsByFilePath);
return formatter(results, {
get cwd() {
return options.cwd;
},
get rulesMeta() {
if (!rulesMeta) {
rulesMeta = createRulesMeta(cliEngine.getRules());
+456 -44
View File
@@ -37,6 +37,8 @@ const
SourceCodeFixer = require("./source-code-fixer"),
timing = require("./timing"),
ruleReplacements = require("../../conf/replacements.json");
const { getRuleFromConfig } = require("../config/flat-config-helpers");
const { FlatConfigArray } = require("../config/flat-config-array");
const debug = require("debug")("eslint:linter");
const MAX_AUTOFIX_PASSES = 10;
@@ -45,6 +47,7 @@ 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");
const globals = require("../../conf/globals");
//------------------------------------------------------------------------------
// Typedefs
@@ -57,6 +60,7 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
/** @typedef {import("../shared/types").GlobalConf} GlobalConf */
/** @typedef {import("../shared/types").LintMessage} LintMessage */
/** @typedef {import("../shared/types").ParserOptions} ParserOptions */
/** @typedef {import("../shared/types").LanguageOptions} LanguageOptions */
/** @typedef {import("../shared/types").Processor} Processor */
/** @typedef {import("../shared/types").Rule} Rule */
@@ -126,6 +130,38 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
// Helpers
//------------------------------------------------------------------------------
/**
* Determines if a given object is Espree.
* @param {Object} parser The parser to check.
* @returns {boolean} True if the parser is Espree or false if not.
*/
function isEspree(parser) {
return !!(parser === espree || parser[parserSymbol] === espree);
}
/**
* Retrieves globals for the given ecmaVersion.
* @param {number} ecmaVersion The version to retrieve globals for.
* @returns {Object} The globals for the given ecmaVersion.
*/
function getGlobalsForEcmaVersion(ecmaVersion) {
switch (ecmaVersion) {
case 3:
return globals.es3;
case 5:
return globals.es5;
default:
if (ecmaVersion < 2015) {
return globals[`es${ecmaVersion + 2009}`];
}
return globals[`es${ecmaVersion}`];
}
}
/**
* Ensures that variables representing built-in properties of the Global Object,
* and any globals declared by special block comments, are present in the global
@@ -268,7 +304,7 @@ function createDisableDirectives(options) {
for (const ruleId of directiveRules) {
// push to directives, if the rule is defined(including null, e.g. /*eslint enable*/)
if (ruleId === null || ruleMapper(ruleId) !== null) {
if (ruleId === null || !!ruleMapper(ruleId)) {
result.directives.push({ parentComment, type, line: commentToken.loc.start.line, column: commentToken.loc.start.column + 1, ruleId });
} else {
result.directiveProblems.push(createLintingProblem({ ruleId, loc: commentToken.loc }));
@@ -400,7 +436,7 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
const rule = ruleMapper(name);
const ruleValue = parseResult.config[name];
if (rule === null) {
if (!rule) {
problems.push(createLintingProblem({ ruleId: name, loc: comment.loc }));
return;
}
@@ -447,7 +483,8 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
* @returns {number} normalized ECMAScript version
*/
function normalizeEcmaVersion(parser, ecmaVersion) {
if ((parser[parserSymbol] || parser) === espree) {
if (isEspree(parser)) {
if (ecmaVersion === "latest") {
return espree.latestEcmaVersion;
}
@@ -460,6 +497,38 @@ function normalizeEcmaVersion(parser, ecmaVersion) {
return ecmaVersion >= 2015 ? ecmaVersion - 2009 : ecmaVersion;
}
/**
* Normalize ECMAScript version from the initial config into languageOptions (year)
* format.
* @param {any} [ecmaVersion] ECMAScript version from the initial config
* @returns {number} normalized ECMAScript version
*/
function normalizeEcmaVersionForLanguageOptions(ecmaVersion) {
switch (ecmaVersion) {
case 3:
return 3;
// void 0 = no ecmaVersion specified so use the default
case 5:
case void 0:
return 5;
default:
if (typeof ecmaVersion === "number") {
return ecmaVersion >= 2015 ? ecmaVersion : ecmaVersion + 2009;
}
}
/*
* We default to the latest supported ecmaVersion for everything else.
* Remember, this is for languageOptions.ecmaVersion, which sets the version
* that is used for a number of processes inside of ESLint. It's normally
* safe to assume people want the latest unless otherwise specified.
*/
return espree.latestEcmaVersion + 2009;
}
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu;
/**
@@ -511,7 +580,11 @@ function normalizeFilename(filename) {
* @returns {Required<VerifyOptions> & InternalOptions} Normalized options
*/
function normalizeVerifyOptions(providedOptions, config) {
const disableInlineConfig = config.noInlineConfig === true;
const linterOptions = config.linterOptions || config;
// .noInlineConfig for eslintrc, .linterOptions.noInlineConfig for flat
const disableInlineConfig = linterOptions.noInlineConfig === true;
const ignoreInlineConfig = providedOptions.allowInlineConfig === false;
const configNameOfNoInlineConfig = config.configNameOfNoInlineConfig
? ` (${config.configNameOfNoInlineConfig})`
@@ -523,7 +596,9 @@ function normalizeVerifyOptions(providedOptions, config) {
reportUnusedDisableDirectives = reportUnusedDisableDirectives ? "error" : "off";
}
if (typeof reportUnusedDisableDirectives !== "string") {
reportUnusedDisableDirectives = config.reportUnusedDisableDirectives ? "warn" : "off";
reportUnusedDisableDirectives =
linterOptions.reportUnusedDisableDirectives
? "warn" : "off";
}
return {
@@ -566,6 +641,30 @@ function resolveParserOptions(parser, providedOptions, enabledEnvironments) {
return mergedParserOptions;
}
/**
* Converts parserOptions to languageOptions for backwards compatibility with eslintrc.
* @param {ConfigData} config Config object.
* @param {Object} config.globals Global variable definitions.
* @param {Parser} config.parser The parser to use.
* @param {ParserOptions} config.parserOptions The parserOptions to use.
* @returns {LanguageOptions} The languageOptions equivalent.
*/
function createLanguageOptions({ globals: configuredGlobals, parser, parserOptions }) {
const {
ecmaVersion,
sourceType
} = parserOptions;
return {
globals: configuredGlobals,
ecmaVersion: normalizeEcmaVersionForLanguageOptions(ecmaVersion),
sourceType,
parser,
parserOptions
};
}
/**
* Combines the provided globals object with the globals from environments
* @param {Record<string, GlobalConf>} providedGlobals The 'globals' key in a config
@@ -614,20 +713,21 @@ function getRuleOptions(ruleConfig) {
/**
* Analyze scope of the given AST.
* @param {ASTNode} ast The `Program` node to analyze.
* @param {ParserOptions} parserOptions The parser options.
* @param {LanguageOptions} languageOptions The parser options.
* @param {Record<string, string[]>} visitorKeys The visitor keys.
* @returns {ScopeManager} The analysis result.
*/
function analyzeScope(ast, parserOptions, visitorKeys) {
function analyzeScope(ast, languageOptions, visitorKeys) {
const parserOptions = languageOptions.parserOptions;
const ecmaFeatures = parserOptions.ecmaFeatures || {};
const ecmaVersion = parserOptions.ecmaVersion || DEFAULT_ECMA_VERSION;
const ecmaVersion = languageOptions.ecmaVersion || DEFAULT_ECMA_VERSION;
return eslintScope.analyze(ast, {
ignoreEval: true,
nodejsScope: ecmaFeatures.globalReturn,
impliedStrict: ecmaFeatures.impliedStrict,
ecmaVersion: typeof ecmaVersion === "number" ? ecmaVersion : 6,
sourceType: parserOptions.sourceType || "script",
sourceType: languageOptions.sourceType || "script",
childVisitorKeys: visitorKeys || evk.KEYS,
fallback: Traverser.getKeys
});
@@ -638,25 +738,29 @@ function analyzeScope(ast, parserOptions, visitorKeys) {
* optimization of functions, so it's best to keep the try-catch as isolated
* as possible
* @param {string} text The text to parse.
* @param {Parser} parser The parser to parse.
* @param {ParserOptions} providedParserOptions Options to pass to the parser
* @param {LanguageOptions} languageOptions Options to pass to the parser
* @param {string} filePath The path to the file being parsed.
* @returns {{success: false, error: Problem}|{success: true, sourceCode: SourceCode}}
* An object containing the AST and parser services if parsing was successful, or the error if parsing failed
* @private
*/
function parse(text, parser, providedParserOptions, filePath) {
function parse(text, languageOptions, filePath) {
const textToParse = stripUnicodeBOM(text).replace(astUtils.shebangPattern, (match, captured) => `//${captured}`);
const parserOptions = Object.assign({}, providedParserOptions, {
loc: true,
range: true,
raw: true,
tokens: true,
comment: true,
eslintVisitorKeys: true,
eslintScopeManager: true,
filePath
});
const { ecmaVersion, sourceType, parser } = languageOptions;
const parserOptions = Object.assign(
{ ecmaVersion, sourceType },
languageOptions.parserOptions,
{
loc: true,
range: true,
raw: true,
tokens: true,
comment: true,
eslintVisitorKeys: true,
eslintScopeManager: true,
filePath
}
);
/*
* Check for parsing errors first. If there's a parsing error, nothing
@@ -671,7 +775,7 @@ function parse(text, parser, providedParserOptions, filePath) {
const ast = parseResult.ast;
const parserServices = parseResult.services || {};
const visitorKeys = parseResult.visitorKeys || evk.KEYS;
const scopeManager = parseResult.scopeManager || analyzeScope(ast, parserOptions, visitorKeys);
const scopeManager = parseResult.scopeManager || analyzeScope(ast, languageOptions, visitorKeys);
return {
success: true,
@@ -740,13 +844,17 @@ function getScope(scopeManager, currentNode) {
* Marks a variable as used in the current scope
* @param {ScopeManager} scopeManager The scope manager for this AST. The scope may be mutated by this function.
* @param {ASTNode} currentNode The node currently being traversed
* @param {Object} parserOptions The options used to parse this text
* @param {LanguageOptions} languageOptions The options used to parse this text
* @param {string} name The name of the variable that should be marked as used.
* @returns {boolean} True if the variable was found and marked as used, false if not.
*/
function markVariableAsUsed(scopeManager, currentNode, parserOptions, name) {
const hasGlobalReturn = parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn;
const specialScope = hasGlobalReturn || parserOptions.sourceType === "module";
function markVariableAsUsed(scopeManager, currentNode, languageOptions, name) {
const parserOptions = languageOptions.parserOptions;
const sourceType = languageOptions.sourceType;
const hasGlobalReturn =
(parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn) ||
sourceType === "commonjs";
const specialScope = hasGlobalReturn || sourceType === "module";
const currentScope = getScope(scopeManager, currentNode);
// Special Node.js scope means we need to start one level deeper
@@ -837,8 +945,8 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
* @param {SourceCode} sourceCode A SourceCode object for the given text
* @param {Object} configuredRules The rules configuration
* @param {function(string): Rule} ruleMapper A mapper function from rule names to rules
* @param {Object} parserOptions The options that were passed to the parser
* @param {string} parserName The name of the parser in the config
* @param {string | undefined} parserName The name of the parser in the config
* @param {LanguageOptions} languageOptions The options for parsing the code.
* @param {Object} settings The settings that were enabled in the config
* @param {string} filename The reported filename of the code
* @param {boolean} disableFixes If true, it doesn't make `fix` properties.
@@ -846,7 +954,7 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
* @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, physicalFilename) {
function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename) {
const emitter = createEmitter();
const nodeQueue = [];
let currentNode = sourceCode.ast;
@@ -878,16 +986,18 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
getPhysicalFilename: () => physicalFilename || filename,
getScope: () => getScope(sourceCode.scopeManager, currentNode),
getSourceCode: () => sourceCode,
markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode, parserOptions, name),
parserOptions,
markVariableAsUsed: name => markVariableAsUsed(sourceCode.scopeManager, currentNode, languageOptions, name),
parserOptions: {
...languageOptions.parserOptions
},
parserPath: parserName,
languageOptions,
parserServices: sourceCode.parserServices,
settings
}
)
);
const lintingProblems = [];
Object.keys(configuredRules).forEach(ruleId => {
@@ -900,7 +1010,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
const rule = ruleMapper(ruleId);
if (rule === null) {
if (!rule) {
lintingProblems.push(createLintingProblem({ ruleId }));
return;
}
@@ -1074,13 +1184,28 @@ function normalizeCwd(cwd) {
*/
const internalSlotsMap = new WeakMap();
/**
* Throws an error when the given linter is in flat config mode.
* @param {Linter} linter The linter to check.
* @returns {void}
* @throws {Error} If the linter is in flat config mode.
*/
function assertEslintrcConfig(linter) {
const { configType } = internalSlotsMap.get(linter);
if (configType === "flat") {
throw new Error("This method cannot be used with flat config. Add your entries directly into the config array.");
}
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
/**
* Object that is responsible for verifying JavaScript text
* @name eslint
* @name Linter
*/
class Linter {
@@ -1088,12 +1213,14 @@ class Linter {
* Initialize the Linter.
* @param {Object} [config] the config object
* @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
* @param {"flat"|"eslintrc"} [config.configType="eslintrc"] the type of config used.
*/
constructor({ cwd } = {}) {
constructor({ cwd, configType } = {}) {
internalSlotsMap.set(this, {
cwd: normalizeCwd(cwd),
lastConfigArray: null,
lastSourceCode: null,
configType, // TODO: Remove after flat config conversion
parserMap: new Map([["espree", espree]]),
ruleMap: new Rules()
});
@@ -1168,12 +1295,16 @@ class Linter {
const parserOptions = resolveParserOptions(parser, config.parserOptions || {}, enabledEnvs);
const configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs);
const settings = config.settings || {};
const languageOptions = createLanguageOptions({
globals: config.globals,
parser,
parserOptions
});
if (!slots.lastSourceCode) {
const parseResult = parse(
text,
parser,
parserOptions,
languageOptions,
options.filename
);
@@ -1194,7 +1325,7 @@ class Linter {
ast: slots.lastSourceCode.ast,
parserServices: slots.lastSourceCode.parserServices,
visitorKeys: slots.lastSourceCode.visitorKeys,
scopeManager: analyzeScope(slots.lastSourceCode.ast, parserOptions)
scopeManager: analyzeScope(slots.lastSourceCode.ast, languageOptions)
});
}
}
@@ -1220,8 +1351,8 @@ class Linter {
sourceCode,
configuredRules,
ruleId => getRule(slots, ruleId),
parserOptions,
parserName,
languageOptions,
settings,
options.filename,
options.disableFixes,
@@ -1270,15 +1401,43 @@ class Linter {
*/
verify(textOrSourceCode, config, filenameOrOptions) {
debug("Verify");
const { configType } = internalSlotsMap.get(this);
const options = typeof filenameOrOptions === "string"
? { filename: filenameOrOptions }
: filenameOrOptions || {};
// CLIEngine passes a `ConfigArray` object.
if (config && typeof config.extractConfig === "function") {
return this._verifyWithConfigArray(textOrSourceCode, config, options);
if (config) {
if (configType === "flat") {
/*
* Because of how Webpack packages up the files, we can't
* compare directly to `FlatConfigArray` using `instanceof`
* because it's not the same `FlatConfigArray` as in the tests.
* So, we work around it by assuming an array is, in fact, a
* `FlatConfigArray` if it has a `getConfig()` method.
*/
let configArray = config;
if (!Array.isArray(config) || typeof config.getConfig !== "function") {
configArray = new FlatConfigArray(config);
configArray.normalizeSync();
}
return this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true);
}
if (typeof config.extractConfig === "function") {
return this._verifyWithConfigArray(textOrSourceCode, config, options);
}
}
/*
* If we get to here, it means `config` is just an object rather
* than a config array so we can go right into linting.
*/
/*
* `Linter` doesn't support `overrides` property in configuration.
* So we cannot apply multiple processors.
@@ -1289,6 +1448,214 @@ class Linter {
return this._verifyWithoutProcessors(textOrSourceCode, config, options);
}
/**
* Verify with a processor.
* @param {string|SourceCode} textOrSourceCode The source code.
* @param {FlatConfig} config The config array.
* @param {VerifyOptions&ProcessorOptions} options The options.
* @param {FlatConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
* @returns {LintMessage[]} The found problems.
*/
_verifyWithFlatConfigArrayAndProcessor(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 || (messagesList => messagesList.flat());
const filterCodeBlock =
options.filterCodeBlock ||
(blockFilename => blockFilename.endsWith(".js"));
const originalExtname = path.extname(filename);
const messageLists = preprocess(text, filenameToExpose).map((block, i) => {
debug("A code block was found: %o", block.filename || "(unnamed)");
// Keep the legacy behavior.
if (typeof block === "string") {
return this._verifyWithFlatConfigArrayAndWithoutProcessors(block, config, options);
}
const blockText = block.text;
const blockName = path.join(filename, `${i}_${block.filename}`);
// Skip this block if filtered.
if (!filterCodeBlock(blockName, blockText)) {
debug("This code block was skipped.");
return [];
}
// 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._verifyWithFlatConfigArray(
blockText,
configForRecursive,
{ ...options, filename: blockName, physicalFilename }
);
}
// Does lint.
return this._verifyWithFlatConfigArrayAndWithoutProcessors(
blockText,
config,
{ ...options, filename: blockName, physicalFilename }
);
});
return postprocess(messageLists, filenameToExpose);
}
/**
* Same as linter.verify, except without support for processors.
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
* @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
* @throws {Error} If during rule execution.
* @returns {LintMessage[]} The results as an array of messages or an empty array if no messages.
*/
_verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, providedConfig, providedOptions) {
const slots = internalSlotsMap.get(this);
const config = providedConfig || {};
const options = normalizeVerifyOptions(providedOptions, config);
let text;
// evaluate arguments
if (typeof textOrSourceCode === "string") {
slots.lastSourceCode = null;
text = textOrSourceCode;
} else {
slots.lastSourceCode = textOrSourceCode;
text = textOrSourceCode.text;
}
const languageOptions = config.languageOptions;
languageOptions.ecmaVersion = normalizeEcmaVersionForLanguageOptions(
languageOptions.ecmaVersion
);
// add configured globals and language globals
const configuredGlobals = {
...(getGlobalsForEcmaVersion(languageOptions.ecmaVersion)),
...(languageOptions.sourceType === "commonjs" ? globals.commonjs : void 0),
...languageOptions.globals
};
// Espree expects this information to be passed in
if (isEspree(languageOptions.parser)) {
const parserOptions = languageOptions.parserOptions;
if (languageOptions.sourceType) {
parserOptions.sourceType = languageOptions.sourceType;
if (
parserOptions.sourceType === "module" &&
parserOptions.ecmaFeatures &&
parserOptions.ecmaFeatures.globalReturn
) {
parserOptions.ecmaFeatures.globalReturn = false;
}
}
}
const settings = config.settings || {};
if (!slots.lastSourceCode) {
const parseResult = parse(
text,
languageOptions,
options.filename
);
if (!parseResult.success) {
return [parseResult.error];
}
slots.lastSourceCode = parseResult.sourceCode;
} else {
/*
* If the given source code object as the first argument does not have scopeManager, analyze the scope.
* This is for backward compatibility (SourceCode is frozen so it cannot rebind).
*/
if (!slots.lastSourceCode.scopeManager) {
slots.lastSourceCode = new SourceCode({
text: slots.lastSourceCode.text,
ast: slots.lastSourceCode.ast,
parserServices: slots.lastSourceCode.parserServices,
visitorKeys: slots.lastSourceCode.visitorKeys,
scopeManager: analyzeScope(slots.lastSourceCode.ast, languageOptions)
});
}
}
const sourceCode = slots.lastSourceCode;
const commentDirectives = options.allowInlineConfig
? getDirectiveComments(
options.filename,
sourceCode.ast,
ruleId => getRuleFromConfig(ruleId, config),
options.warnInlineConfig
)
: { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
// augment global scope with declared global variables
addDeclaredGlobals(
sourceCode.scopeManager.scopes[0],
configuredGlobals,
{ exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }
);
const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
let lintingProblems;
try {
lintingProblems = runRules(
sourceCode,
configuredRules,
ruleId => getRuleFromConfig(ruleId, config),
void 0,
languageOptions,
settings,
options.filename,
options.disableFixes,
slots.cwd,
providedOptions.physicalFilename
);
} catch (err) {
err.message += `\nOccurred while linting ${options.filename}`;
debug("An error occurred while traversing");
debug("Filename:", options.filename);
if (err.currentNode) {
const { line } = err.currentNode.loc.start;
debug("Line:", line);
err.message += `:${line}`;
}
debug("Parser Options:", languageOptions.parserOptions);
// debug("Parser Path:", parserName);
debug("Settings:", settings);
if (err.ruleId) {
err.message += `\nRule: "${err.ruleId}"`;
}
throw err;
}
return applyDisableDirectives({
directives: commentDirectives.disableDirectives,
disableFixes: options.disableFixes,
problems: lintingProblems
.concat(commentDirectives.problems)
.sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
reportUnusedDisableDirectives: options.reportUnusedDisableDirectives
});
}
/**
* Verify a given code with `ConfigArray`.
* @param {string|SourceCode} textOrSourceCode The source code.
@@ -1324,6 +1691,47 @@ class Linter {
return this._verifyWithoutProcessors(textOrSourceCode, config, options);
}
/**
* Verify a given code with a flat config.
* @param {string|SourceCode} textOrSourceCode The source code.
* @param {FlatConfigArray} configArray The config array.
* @param {VerifyOptions&ProcessorOptions} options The options.
* @param {boolean} [firstCall=false] Indicates if this is being called directly
* from verify(). (TODO: Remove once eslintrc is removed.)
* @returns {LintMessage[]} The found problems.
*/
_verifyWithFlatConfigArray(textOrSourceCode, configArray, options, firstCall = false) {
debug("With flat config: %s", options.filename);
// we need a filename to match configs against
const filename = options.filename || "<input>";
// Store the config array in order to get plugin envs and rules later.
internalSlotsMap.get(this).lastConfigArray = configArray;
const config = configArray.getConfig(filename);
// Verify.
if (config.processor) {
debug("Apply the processor: %o", config.processor);
const { preprocess, postprocess, supportsAutofix } = config.processor;
const disableFixes = options.disableFixes || !supportsAutofix;
return this._verifyWithFlatConfigArrayAndProcessor(
textOrSourceCode,
config,
{ ...options, filename, disableFixes, postprocess, preprocess },
configArray
);
}
// check for options-based processing
if (firstCall && (options.preprocess || options.postprocess)) {
return this._verifyWithFlatConfigArrayAndProcessor(textOrSourceCode, config, options);
}
return this._verifyWithFlatConfigArrayAndWithoutProcessors(textOrSourceCode, config, options);
}
/**
* Verify with a processor.
* @param {string|SourceCode} textOrSourceCode The source code.
@@ -1397,6 +1805,7 @@ class Linter {
* @returns {void}
*/
defineRule(ruleId, ruleModule) {
assertEslintrcConfig(this);
internalSlotsMap.get(this).ruleMap.define(ruleId, ruleModule);
}
@@ -1406,6 +1815,7 @@ class Linter {
* @returns {void}
*/
defineRules(rulesToDefine) {
assertEslintrcConfig(this);
Object.getOwnPropertyNames(rulesToDefine).forEach(ruleId => {
this.defineRule(ruleId, rulesToDefine[ruleId]);
});
@@ -1416,6 +1826,7 @@ class Linter {
* @returns {Map<string, Rule>} All loaded rules
*/
getRules() {
assertEslintrcConfig(this);
const { lastConfigArray, ruleMap } = internalSlotsMap.get(this);
return new Map(function *() {
@@ -1434,6 +1845,7 @@ class Linter {
* @returns {void}
*/
defineParser(parserId, parserModule) {
assertEslintrcConfig(this);
internalSlotsMap.get(this).parserMap.set(parserId, parserModule);
}
@@ -1441,7 +1853,7 @@ class Linter {
* Performs multiple autofix passes over the text until as many fixes as possible
* have been applied.
* @param {string} text The source text to apply fixes to.
* @param {ConfigData|ConfigArray} config The ESLint config object to use.
* @param {ConfigData|ConfigArray|FlatConfigArray} config The ESLint config object to use.
* @param {VerifyOptions&ProcessorOptions&FixOptions} options The ESLint options object to use.
* @returns {{fixed:boolean,messages:LintMessage[],output:string}} The result of the fix operation as returned from the
* SourceCodeFixer.
+6 -6
View File
@@ -50,7 +50,7 @@ const optionator = require("optionator");
* @property {boolean | undefined} reportUnusedDisableDirectives Adds reported errors for unused eslint-disable directives
* @property {string} [resolvePluginsRelativeTo] A folder where plugins should be resolved from, CWD by default
* @property {Object} [rule] Specify rules
* @property {string[]} [rulesdir] Use additional rules from this directory
* @property {string[]} [rulesdir] Load additional rules from this directory. Deprecated: Use rules from plugins
* @property {boolean} stdin Lint code provided on <STDIN>
* @property {string} [stdinFilename] Specify filename to process STDIN as
* @property {boolean} quiet Report errors only
@@ -118,11 +118,6 @@ module.exports = optionator({
{
heading: "Specifying rules and plugins"
},
{
option: "rulesdir",
type: "[path::String]",
description: "Use additional rules from this directory"
},
{
option: "plugin",
type: "[String]",
@@ -133,6 +128,11 @@ module.exports = optionator({
type: "Object",
description: "Specify rules"
},
{
option: "rulesdir",
type: "[path::String]",
description: "Load additional rules from this directory. Deprecated: Use rules from plugins"
},
{
heading: "Fixing problems"
},
+1
View File
@@ -134,6 +134,7 @@ function isPropertyDescriptor(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -11,6 +11,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -10,6 +10,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -133,6 +133,7 @@ function getArrayMethodName(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
+1
View File
@@ -11,6 +11,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -14,6 +14,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -27,6 +27,7 @@ function hasBlockBody(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -14,6 +14,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -8,6 +8,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -11,6 +11,7 @@ const util = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -11,6 +11,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
deprecated: true,
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -99,6 +99,7 @@ function createRegExpForIgnorePatterns(normalizedOptions) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -15,6 +15,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -70,6 +70,7 @@ function normalizeOptions(optionValue, ecmaVersion) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -10,6 +10,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -11,6 +11,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -17,6 +17,7 @@ const { upperCaseFirst } = require("../shared/string-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -10,6 +10,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -40,6 +40,7 @@ function isClassConstructor(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -8,6 +8,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -116,6 +116,7 @@ function isPossibleConstructor(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
+1
View File
@@ -14,6 +14,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -10,6 +10,7 @@ const DEFAULT_COMMENT_PATTERN = /^no default$/iu;
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -5,6 +5,7 @@
"use strict";
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -11,6 +11,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -20,6 +20,7 @@ const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/u;
// `null` literal must be handled separately.
const literalTypesToCheck = new Set(["string", "boolean"]);
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -8,6 +8,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -15,6 +15,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
+1
View File
@@ -15,6 +15,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -68,6 +68,7 @@ const optionsObject = {
additionalProperties: false
};
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -24,6 +24,7 @@ function isFunctionName(variable) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -8,6 +8,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -14,6 +14,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -25,6 +25,7 @@ const OVERRIDE_SCHEMA = {
]
};
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -29,6 +29,7 @@ function isReachable(segment) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
+1
View File
@@ -48,6 +48,7 @@ function isShadowed(scope, node) {
return reference && reference.resolved && reference.resolved.defs.length > 0;
}
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
deprecated: true,
+1
View File
@@ -90,6 +90,7 @@ function isAccessorKind(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -10,6 +10,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
deprecated: true,
+1
View File
@@ -110,6 +110,7 @@ function isShorthandPropertyDefinition(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
deprecated: true,
+1
View File
@@ -93,6 +93,7 @@ function isPropertyNameInDestructuring(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -10,6 +10,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -9,6 +9,7 @@ const { isCommentToken, isNotOpeningParenToken } = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -20,6 +20,7 @@ const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
/* istanbul ignore next: this rule has known coverage issues, but it's deprecated and shouldn't be updated in the future anyway. */
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -494,6 +494,7 @@ const ELEMENT_LIST_SCHEMA = {
]
};
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -42,6 +42,7 @@ function isInitialized(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -36,6 +36,7 @@ const QUOTE_SETTINGS = {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -133,6 +133,7 @@ function initOptions(toOptions, fromOptions) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -61,6 +61,7 @@ function isCloseParenOfTemplate(token) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -10,6 +10,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -15,6 +15,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -49,6 +49,7 @@ function getCommentLineNums(comments) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -12,6 +12,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -14,6 +14,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -13,6 +13,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -63,6 +63,7 @@ const OPTIONS_OR_INTEGER_SCHEMA = {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+21 -2
View File
@@ -65,6 +65,7 @@ function getCommentLineNumbers(comments) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
@@ -79,7 +80,7 @@ module.exports = {
OPTIONS_OR_INTEGER_SCHEMA
],
messages: {
exceed: "{{name}} has too many lines ({{lineCount}}). Maximum allowed is {{maxLines}}."
exceed: "{{name}} has exceeded the limit of lines allowed by {{linesExceed}}. Maximum allowed number of lines per function is {{maxLines}}."
}
},
@@ -169,18 +170,26 @@ module.exports = {
return;
}
let lineCount = 0;
let comments = 0;
let blankLines = 0;
for (let i = node.loc.start.line - 1; i < node.loc.end.line; ++i) {
const line = lines[i];
if (skipComments) {
if (commentLineNumbers.has(i + 1) && isFullLineComment(line, i + 1, commentLineNumbers.get(i + 1))) {
if (lineCount <= maxLines) {
comments++;
}
continue;
}
}
if (skipBlankLines) {
if (line.match(/^\s*$/u)) {
if (lineCount <= maxLines) {
blankLines++;
}
continue;
}
}
@@ -190,11 +199,21 @@ module.exports = {
if (lineCount > maxLines) {
const name = upperCaseFirst(astUtils.getFunctionNameWithKind(funcNode));
const linesExceed = lineCount - maxLines;
const loc = {
start: {
line: node.loc.start.line + maxLines + (comments + blankLines),
column: 0
},
end: node.loc.end
};
context.report({
node,
loc,
messageId: "exceed",
data: { name, lineCount, maxLines }
data: { name, linesExceed, maxLines }
});
}
}
+1
View File
@@ -28,6 +28,7 @@ function range(start, end) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -16,6 +16,7 @@ const { upperCaseFirst } = require("../shared/string-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -14,6 +14,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -16,6 +16,7 @@ const { upperCaseFirst } = require("../shared/string-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -10,6 +10,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -11,6 +11,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -76,6 +76,7 @@ function calculateCapIsNewExceptions(config) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -19,6 +19,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -16,6 +16,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -12,6 +12,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "layout",
+1
View File
@@ -82,6 +82,7 @@ function isGlobalThisReferenceOrGlobalWindow(scope, node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -8,6 +8,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
+1
View File
@@ -53,6 +53,7 @@ function isLooped(node, parent) {
}
}
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
+1
View File
@@ -20,6 +20,7 @@ const BITWISE_OPERATORS = [
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
deprecated: true,
+1
View File
@@ -9,6 +9,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -8,6 +8,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -16,6 +16,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -11,6 +11,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
+1
View File
@@ -8,6 +8,7 @@
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
+1
View File
@@ -28,6 +28,7 @@ const NODE_DESCRIPTIONS = {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
+1
View File
@@ -25,6 +25,7 @@ function isConditional(node) {
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
+1
View File
@@ -15,6 +15,7 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
Loaded 100 of 1103 files, more files were not shown because too many files have changed in this diff. Show more