Comparing version 8.33.0 to 8.38.0
@@ -9,3 +9,3 @@ { | ||
"name": "Deprecated", | ||
"description": "These rules have been deprecated in accordance with the <a href=\"/docs/use/rule-deprecation\">deprecation policy</a>, and replaced by newer rules:", | ||
"description": "These rules have been deprecated in accordance with the <a href=\"{{ '/use/rule-deprecation' | url }}\">deprecation policy</a>, and replaced by newer rules:", | ||
"rules": [] | ||
@@ -15,3 +15,3 @@ }, | ||
"name": "Removed", | ||
"description": "These rules from older versions of ESLint (before the <a href=\"/docs/use/rule-deprecation\">deprecation policy</a> existed) have been replaced by newer rules:", | ||
"description": "These rules from older versions of ESLint (before the <a href=\"{{ '/use/rule-deprecation' | url }}\">deprecation policy</a> existed) have been replaced by newer rules:", | ||
"rules": [ | ||
@@ -18,0 +18,0 @@ { "removed": "generator-star", "replacedBy": ["generator-star-spacing"] }, |
@@ -618,4 +618,4 @@ /** | ||
loadRules, | ||
getEslintRecommendedConfig: () => require("../../conf/eslint-recommended.js"), | ||
getEslintAllConfig: () => require("../../conf/eslint-all.js") | ||
getEslintRecommendedConfig: () => require("@eslint/js").configs.recommended, | ||
getEslintAllConfig: () => require("@eslint/js").configs.all | ||
}); | ||
@@ -622,0 +622,0 @@ const fileEnumerator = new FileEnumerator({ |
@@ -220,4 +220,4 @@ /** | ||
cwd, | ||
getEslintRecommendedConfig: () => require("../../conf/eslint-recommended.js"), | ||
getEslintAllConfig: () => require("../../conf/eslint-all.js") | ||
getEslintRecommendedConfig: () => require("@eslint/js").configs.recommended, | ||
getEslintAllConfig: () => require("@eslint/js").configs.all | ||
}), | ||
@@ -353,3 +353,3 @@ extensions = null, | ||
if (globInputPaths && isGlobPattern(pattern)) { | ||
return this._iterateFilesWithGlob(absolutePath, isDot); | ||
return this._iterateFilesWithGlob(pattern, isDot); | ||
} | ||
@@ -403,4 +403,6 @@ | ||
const directoryPath = path.resolve(getGlobParent(pattern)); | ||
const globPart = pattern.slice(directoryPath.length + 1); | ||
const { cwd } = internalSlotsMap.get(this); | ||
const directoryPath = path.resolve(cwd, getGlobParent(pattern)); | ||
const absolutePath = path.resolve(cwd, pattern); | ||
const globPart = absolutePath.slice(directoryPath.length + 1); | ||
@@ -412,3 +414,3 @@ /* | ||
const recursive = /\*\*|\/|\\/u.test(globPart); | ||
const selector = new Minimatch(pattern, minimatchOpts); | ||
const selector = new Minimatch(absolutePath, minimatchOpts); | ||
@@ -415,0 +417,0 @@ debug(`recursive? ${recursive}`); |
@@ -22,5 +22,2 @@ /** | ||
"@": { | ||
parsers: { | ||
espree: require("espree") | ||
}, | ||
@@ -47,3 +44,3 @@ /* | ||
ecmaVersion: "latest", | ||
parser: "@/espree", | ||
parser: require("espree"), | ||
parserOptions: {} | ||
@@ -50,0 +47,0 @@ } |
@@ -16,3 +16,3 @@ /** | ||
const { defaultConfig } = require("./default-config"); | ||
const recommendedConfig = require("../../conf/eslint-recommended"); | ||
const jsPlugin = require("@eslint/js"); | ||
@@ -40,2 +40,41 @@ //----------------------------------------------------------------------------- | ||
/** | ||
* Returns the name of an object in the config by reading its `meta` key. | ||
* @param {Object} object The object to check. | ||
* @returns {string?} The name of the object if found or `null` if there | ||
* is no name. | ||
*/ | ||
function getObjectId(object) { | ||
// first check old-style name | ||
let name = object.name; | ||
if (!name) { | ||
if (!object.meta) { | ||
return null; | ||
} | ||
name = object.meta.name; | ||
if (!name) { | ||
return null; | ||
} | ||
} | ||
// now check for old-style version | ||
let version = object.version; | ||
if (!version) { | ||
version = object.meta && object.meta.version; | ||
} | ||
// if there's a version then append that | ||
if (version) { | ||
return `${name}@${version}`; | ||
} | ||
return name; | ||
} | ||
const originalBaseConfig = Symbol("originalBaseConfig"); | ||
@@ -101,3 +140,9 @@ | ||
if (config === "eslint:recommended") { | ||
return recommendedConfig; | ||
// if we are in a Node.js environment warn the user | ||
if (typeof process !== "undefined" && process.emitWarning) { | ||
process.emitWarning("The 'eslint:recommended' string configuration is deprecated and will be replaced by the @eslint/js package's 'recommended' config."); | ||
} | ||
return jsPlugin.configs.recommended; | ||
} | ||
@@ -107,8 +152,8 @@ | ||
/* | ||
* Load `eslint-all.js` here instead of at the top level to avoid loading all rule modules | ||
* when it isn't necessary. `eslint-all.js` reads `meta` of rule objects to filter out deprecated ones, | ||
* so requiring `eslint-all.js` module loads all rule modules as a consequence. | ||
*/ | ||
return require("../../conf/eslint-all"); | ||
// if we are in a Node.js environment warn the user | ||
if (typeof process !== "undefined" && process.emitWarning) { | ||
process.emitWarning("The 'eslint:all' string configuration is deprecated and will be replaced by the @eslint/js package's 'all' config."); | ||
} | ||
return jsPlugin.configs.all; | ||
} | ||
@@ -152,12 +197,11 @@ | ||
if (languageOptions && languageOptions.parser) { | ||
if (typeof languageOptions.parser === "string") { | ||
const { pluginName, objectName: localParserName } = splitPluginIdentifier(languageOptions.parser); | ||
const { parser } = languageOptions; | ||
parserName = languageOptions.parser; | ||
if (typeof parser === "object") { | ||
parserName = getObjectId(parser); | ||
if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[localParserName]) { | ||
throw new TypeError(`Key "parser": Could not find "${localParserName}" in plugin "${pluginName}".`); | ||
if (!parserName) { | ||
invalidParser = true; | ||
} | ||
languageOptions.parser = plugins[pluginName].parsers[localParserName]; | ||
} else { | ||
@@ -180,2 +224,9 @@ invalidParser = true; | ||
config.processor = plugins[pluginName].processors[localProcessorName]; | ||
} else if (typeof processor === "object") { | ||
processorName = getObjectId(processor); | ||
if (!processorName) { | ||
invalidProcessor = true; | ||
} | ||
} else { | ||
@@ -194,7 +245,7 @@ invalidProcessor = true; | ||
if (invalidParser) { | ||
throw new Error("Caching is not supported when parser is an object."); | ||
throw new Error("Could not serialize parser object (missing 'meta' object)."); | ||
} | ||
if (invalidProcessor) { | ||
throw new Error("Caching is not supported when processor is an object."); | ||
throw new Error("Could not serialize processor object (missing 'meta' object)."); | ||
} | ||
@@ -204,3 +255,12 @@ | ||
...this, | ||
plugins: Object.keys(plugins), | ||
plugins: Object.entries(plugins).map(([namespace, plugin]) => { | ||
const pluginId = getObjectId(plugin); | ||
if (!pluginId) { | ||
return namespace; | ||
} | ||
return `${namespace}:${pluginId}`; | ||
}), | ||
languageOptions: { | ||
@@ -207,0 +267,0 @@ ...languageOptions, |
@@ -182,14 +182,2 @@ /** | ||
/** | ||
* 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."); | ||
} | ||
} | ||
//----------------------------------------------------------------------------- | ||
@@ -246,11 +234,9 @@ // Low-Level Schemas | ||
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 (!value || typeof value !== "object" || | ||
(typeof value.parse !== "function" && typeof value.parseForESLint !== "function") | ||
) { | ||
throw new TypeError("Expected object with parse() or parseForESLint() method."); | ||
} | ||
if (typeof value === "string") { | ||
assertIsPluginMemberName(value); | ||
} | ||
} | ||
@@ -257,0 +243,0 @@ }; |
@@ -226,3 +226,3 @@ /** | ||
* or an empty array if there are no matches. | ||
* @throws {UnmatchedSearchPatternsErrror} If there is a pattern that doesn't | ||
* @throws {UnmatchedSearchPatternsError} If there is a pattern that doesn't | ||
* match any files. | ||
@@ -530,5 +530,5 @@ */ | ||
// save patterns for later use based on whether globs are enabled | ||
if (globInputPaths && isGlobPattern(filePath)) { | ||
if (globInputPaths && isGlobPattern(pattern)) { | ||
const basePath = globParent(filePath); | ||
const basePath = path.resolve(cwd, globParent(pattern)); | ||
@@ -573,37 +573,2 @@ // group in cwd if possible and split out others | ||
/** | ||
* Checks whether a file exists at the given location | ||
* @param {string} resolvedPath A path from the CWD | ||
* @throws {Error} As thrown by `fs.statSync` or `fs.isFile`. | ||
* @returns {boolean} `true` if a file exists | ||
*/ | ||
function fileExists(resolvedPath) { | ||
try { | ||
return fs.statSync(resolvedPath).isFile(); | ||
} catch (error) { | ||
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) { | ||
return false; | ||
} | ||
throw error; | ||
} | ||
} | ||
/** | ||
* Checks whether a directory exists at the given location | ||
* @param {string} resolvedPath A path from the CWD | ||
* @throws {Error} As thrown by `fs.statSync` or `fs.isDirectory`. | ||
* @returns {boolean} `true` if a directory exists | ||
*/ | ||
function directoryExists(resolvedPath) { | ||
try { | ||
return fs.statSync(resolvedPath).isDirectory(); | ||
} catch (error) { | ||
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) { | ||
return false; | ||
} | ||
throw error; | ||
} | ||
} | ||
//----------------------------------------------------------------------------- | ||
@@ -930,4 +895,2 @@ // Results-related Helpers | ||
isGlobPattern, | ||
directoryExists, | ||
fileExists, | ||
findFiles, | ||
@@ -934,0 +897,0 @@ |
@@ -348,3 +348,3 @@ /** | ||
static setDefaultConfig(config) { | ||
if (typeof config !== "object") { | ||
if (typeof config !== "object" || config === null) { | ||
throw new TypeError("FlatRuleTester.setDefaultConfig: config must be an object"); | ||
@@ -351,0 +351,0 @@ } |
@@ -415,3 +415,3 @@ /** | ||
static setDefaultConfig(config) { | ||
if (typeof config !== "object") { | ||
if (typeof config !== "object" || config === null) { | ||
throw new TypeError("RuleTester.setDefaultConfig: config must be an object"); | ||
@@ -418,0 +418,0 @@ } |
@@ -19,3 +19,3 @@ /** | ||
const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u; | ||
const TARGET_METHODS = /^(?:every|filter|find(?:Last)?(?:Index)?|flatMap|forEach|map|reduce(?:Right)?|some|sort)$/u; | ||
const TARGET_METHODS = /^(?:every|filter|find(?:Last)?(?:Index)?|flatMap|forEach|map|reduce(?:Right)?|some|sort|toSorted)$/u; | ||
@@ -22,0 +22,0 @@ /** |
@@ -50,2 +50,3 @@ /** | ||
}, | ||
type: "array", | ||
items: [ | ||
@@ -52,0 +53,0 @@ { |
@@ -31,2 +31,3 @@ /** | ||
let stack = []; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -87,3 +88,3 @@ /** | ||
// Gets declared variables, and checks its references. | ||
const variables = context.getDeclaredVariables(node); | ||
const variables = sourceCode.getDeclaredVariables(node); | ||
@@ -90,0 +91,0 @@ for (let i = 0; i < variables.length; ++i) { |
@@ -76,2 +76,3 @@ /** | ||
const allow = options.allow || []; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -249,4 +250,4 @@ //-------------------------------------------------------------------------- | ||
// Report camelcase of global variable references ------------------ | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
@@ -300,3 +301,3 @@ if (!ignoreGlobals) { | ||
]](node) { | ||
for (const variable of context.getDeclaredVariables(node)) { | ||
for (const variable of sourceCode.getDeclaredVariables(node)) { | ||
if (isGoodName(variable.name)) { | ||
@@ -351,3 +352,3 @@ continue; | ||
ImportDeclaration(node) { | ||
for (const variable of context.getDeclaredVariables(node)) { | ||
for (const variable of sourceCode.getDeclaredVariables(node)) { | ||
if (isGoodName(variable.name)) { | ||
@@ -354,0 +355,0 @@ continue; |
@@ -39,2 +39,3 @@ /** | ||
let aliases = []; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -119,6 +120,7 @@ if (context.options.length === 0) { | ||
* Check each alias to ensure that is was assigned to the correct value. | ||
* @param {ASTNode} node The node that represents the scope to check. | ||
* @returns {void} | ||
*/ | ||
function ensureWasAssigned() { | ||
const scope = context.getScope(); | ||
function ensureWasAssigned(node) { | ||
const scope = sourceCode.getScope(node); | ||
@@ -125,0 +127,0 @@ aliases.forEach(alias => { |
@@ -162,3 +162,3 @@ /** | ||
// Skip recursive functions. | ||
const nameVar = context.getDeclaredVariables(node)[0]; | ||
const nameVar = sourceCode.getDeclaredVariables(node)[0]; | ||
@@ -165,0 +165,0 @@ if (isFunctionName(nameVar) && nameVar.references.length > 0) { |
@@ -74,8 +74,10 @@ /** | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
CallExpression(node) { | ||
const currentScope = context.getScope(); | ||
const currentScope = sourceCode.getScope(node); | ||
if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) { | ||
const isGoodRequire = context.getAncestors().every(parent => ACCEPTABLE_PARENTS.has(parent.type)); | ||
const isGoodRequire = sourceCode.getAncestors(node).every(parent => ACCEPTABLE_PARENTS.has(parent.type)); | ||
@@ -82,0 +84,0 @@ if (!isGoodRequire) { |
@@ -41,2 +41,3 @@ /** | ||
const errorArgument = context.options[0] || "err"; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -83,3 +84,3 @@ /** | ||
function checkForError(node) { | ||
const scope = context.getScope(), | ||
const scope = sourceCode.getScope(node), | ||
parameters = getParameters(scope), | ||
@@ -86,0 +87,0 @@ firstParameter = parameters[0]; |
@@ -143,2 +143,3 @@ /** | ||
const reportedNodes = new Set(); | ||
const sourceCode = context.getSourceCode(); | ||
@@ -235,4 +236,4 @@ let globalScope; | ||
Program() { | ||
globalScope = context.getScope(); | ||
Program(node) { | ||
globalScope = sourceCode.getScope(node); | ||
}, | ||
@@ -239,0 +240,0 @@ |
@@ -124,2 +124,3 @@ /** | ||
const reportedNodes = new Set(); | ||
const sourceCode = context.getSourceCode(); | ||
@@ -214,4 +215,4 @@ let globalScope; | ||
Program() { | ||
globalScope = context.getScope(); | ||
Program(node) { | ||
globalScope = sourceCode.getScope(node); | ||
}, | ||
@@ -218,0 +219,0 @@ |
@@ -70,2 +70,3 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
let globalScope; | ||
@@ -174,4 +175,4 @@ | ||
Program() { | ||
globalScope = context.getScope(); | ||
Program(node) { | ||
globalScope = sourceCode.getScope(node); | ||
}, | ||
@@ -178,0 +179,0 @@ |
@@ -116,2 +116,6 @@ /** | ||
type: "boolean" | ||
}, | ||
afterHashbangComment: { | ||
type: "boolean", | ||
default: false | ||
} | ||
@@ -453,2 +457,9 @@ }, | ||
} | ||
} else if (token.type === "Shebang") { | ||
if (options.afterHashbangComment) { | ||
checkForEmptyLine(token, { | ||
after: options.afterHashbangComment, | ||
before: false | ||
}); | ||
} | ||
} | ||
@@ -455,0 +466,0 @@ }); |
@@ -115,3 +115,3 @@ /** | ||
* truthiness checks: value, Boolean(value), !!value | ||
* falsyness checks: !value, !Boolean(value) | ||
* falsiness checks: !value, !Boolean(value) | ||
* nullish checks: value == null, value === undefined || value === null | ||
@@ -163,3 +163,3 @@ * @param {ASTNode} expression Test condition | ||
docs: { | ||
description: "Require or disallow logical assignment logical operator shorthand", | ||
description: "Require or disallow logical assignment operator shorthand", | ||
recommended: false, | ||
@@ -211,3 +211,3 @@ url: "https://eslint.org/docs/rules/logical-assignment-operators" | ||
const sourceCode = context.getSourceCode(); | ||
const isStrict = context.getScope().isStrict; | ||
const isStrict = sourceCode.getScope(sourceCode.ast).isStrict; | ||
@@ -415,3 +415,3 @@ /** | ||
const body = hasBody ? ifNode.consequent.body[0] : ifNode.consequent; | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(ifNode); | ||
const existence = getExistence(ifNode.test, scope); | ||
@@ -418,0 +418,0 @@ |
@@ -25,3 +25,33 @@ /** | ||
fixable: "whitespace", | ||
schema: [{ enum: ["starred-block", "separate-lines", "bare-block"] }], | ||
schema: { | ||
anyOf: [ | ||
{ | ||
type: "array", | ||
items: [ | ||
{ | ||
enum: ["starred-block", "bare-block"] | ||
} | ||
], | ||
additionalItems: false | ||
}, | ||
{ | ||
type: "array", | ||
items: [ | ||
{ | ||
enum: ["separate-lines"] | ||
}, | ||
{ | ||
type: "object", | ||
properties: { | ||
checkJSDoc: { | ||
type: "boolean" | ||
} | ||
}, | ||
additionalProperties: false | ||
} | ||
], | ||
additionalItems: false | ||
} | ||
] | ||
}, | ||
messages: { | ||
@@ -41,2 +71,4 @@ expectedBlock: "Expected a block comment instead of consecutive line comments.", | ||
const option = context.options[0] || "starred-block"; | ||
const params = context.options[1] || {}; | ||
const checkJSDoc = !!params.checkJSDoc; | ||
@@ -338,7 +370,14 @@ //---------------------------------------------------------------------- | ||
if (firstComment.type !== "Block" || isJSDocComment(commentGroup)) { | ||
const isJSDoc = isJSDocComment(commentGroup); | ||
if (firstComment.type !== "Block" || (!checkJSDoc && isJSDoc)) { | ||
return; | ||
} | ||
const commentLines = getCommentLines(commentGroup); | ||
let commentLines = getCommentLines(commentGroup); | ||
if (isJSDoc) { | ||
commentLines = commentLines.slice(1, commentLines.length - 1); | ||
} | ||
const tokenAfter = sourceCode.getTokenAfter(firstComment, { includeComments: true }); | ||
@@ -345,0 +384,0 @@ |
@@ -34,16 +34,7 @@ /** | ||
fixable: "code", | ||
schema: { | ||
anyOf: [ | ||
{ | ||
type: "array", | ||
items: [ | ||
{ | ||
enum: ["always", "never"] | ||
} | ||
], | ||
minItems: 0, | ||
maxItems: 1 | ||
} | ||
] | ||
}, | ||
schema: [ | ||
{ | ||
enum: ["always", "never"] | ||
} | ||
], | ||
messages: { | ||
@@ -50,0 +41,0 @@ missing: "Missing '()' invoking a constructor.", |
@@ -104,6 +104,8 @@ /** | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
CallExpression(node) { | ||
const callee = skipChainExpression(node.callee), | ||
currentScope = context.getScope(); | ||
currentScope = sourceCode.getScope(node); | ||
@@ -110,0 +112,0 @@ // without window. |
@@ -42,2 +42,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
//-------------------------------------------------------------------------- | ||
@@ -64,3 +66,3 @@ // Helpers | ||
"CatchClause[param!=null]"(node) { | ||
let scope = context.getScope(); | ||
let scope = sourceCode.getScope(node); | ||
@@ -67,0 +69,0 @@ /* |
@@ -34,2 +34,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -53,3 +55,3 @@ * Finds and reports references that are non initializer and writable. | ||
function checkForClass(node) { | ||
context.getDeclaredVariables(node).forEach(checkVariable); | ||
sourceCode.getDeclaredVariables(node).forEach(checkVariable); | ||
} | ||
@@ -56,0 +58,0 @@ |
@@ -54,2 +54,3 @@ /** | ||
const allowed = options.allow || []; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -113,4 +114,4 @@ /** | ||
return { | ||
"Program:exit"() { | ||
const scope = context.getScope(); | ||
"Program:exit"(node) { | ||
const scope = sourceCode.getScope(node); | ||
const consoleVar = astUtils.getVariableByName(scope, "console"); | ||
@@ -117,0 +118,0 @@ const shadowed = consoleVar && consoleVar.defs.length > 0; |
@@ -34,2 +34,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -49,3 +51,3 @@ * Finds and reports references that are non initializer and writable. | ||
if (node.kind === "const") { | ||
context.getDeclaredVariables(node).forEach(checkVariable); | ||
sourceCode.getDeclaredVariables(node).forEach(checkVariable); | ||
} | ||
@@ -52,0 +54,0 @@ } |
@@ -18,2 +18,19 @@ /** | ||
/** | ||
* Checks whether or not a node is `null` or `undefined`. Similar to the one | ||
* found in ast-utils.js, but this one correctly handles the edge case that | ||
* `undefined` has been redefined. | ||
* @param {Scope} scope Scope in which the expression was found. | ||
* @param {ASTNode} node A node to check. | ||
* @returns {boolean} Whether or not the node is a `null` or `undefined`. | ||
* @public | ||
*/ | ||
function isNullOrUndefined(scope, node) { | ||
return ( | ||
isNullLiteral(node) || | ||
(node.type === "Identifier" && node.name === "undefined" && isReferenceToGlobalVariable(scope, node)) || | ||
(node.type === "UnaryExpression" && node.operator === "void") | ||
); | ||
} | ||
/** | ||
* Test if an AST node has a statically knowable constant nullishness. Meaning, | ||
@@ -25,5 +42,10 @@ * it will always resolve to a constant value of either: `null`, `undefined` | ||
* @param {ASTNode} node The AST node being tested. | ||
* @param {boolean} nonNullish if `true` then nullish values are not considered constant. | ||
* @returns {boolean} Does `node` have constant nullishness? | ||
*/ | ||
function hasConstantNullishness(scope, node) { | ||
function hasConstantNullishness(scope, node, nonNullish) { | ||
if (nonNullish && isNullOrUndefined(scope, node)) { | ||
return false; | ||
} | ||
switch (node.type) { | ||
@@ -50,5 +72,8 @@ case "ObjectExpression": // Objects are never nullish | ||
} | ||
case "LogicalExpression": { | ||
return node.operator === "??" && hasConstantNullishness(scope, node.right, true); | ||
} | ||
case "AssignmentExpression": | ||
if (node.operator === "=") { | ||
return hasConstantNullishness(scope, node.right); | ||
return hasConstantNullishness(scope, node.right, nonNullish); | ||
} | ||
@@ -86,3 +111,3 @@ | ||
return hasConstantNullishness(scope, last); | ||
return hasConstantNullishness(scope, last, nonNullish); | ||
} | ||
@@ -355,3 +380,3 @@ case "Identifier": | ||
* | ||
* Catching these is especially useful for primitive constructures | ||
* Catching these is especially useful for primitive constructors | ||
* which return boxed values, a surprising gotcha' in JavaScript. | ||
@@ -387,20 +412,2 @@ */ | ||
/** | ||
* Checks whether or not a node is `null` or `undefined`. Similar to the one | ||
* found in ast-utils.js, but this one correctly handles the edge case that | ||
* `undefined` has been redefined. | ||
* @param {Scope} scope Scope in which the expression was found. | ||
* @param {ASTNode} node A node to check. | ||
* @returns {boolean} Whether or not the node is a `null` or `undefined`. | ||
* @public | ||
*/ | ||
function isNullOrUndefined(scope, node) { | ||
return ( | ||
isNullLiteral(node) || | ||
(node.type === "Identifier" && node.name === "undefined" && isReferenceToGlobalVariable(scope, node)) || | ||
(node.type === "UnaryExpression" && node.operator === "void") | ||
); | ||
} | ||
/** | ||
* Checks if one operand will cause the result to be constant. | ||
@@ -416,3 +423,3 @@ * @param {Scope} scope Scope in which the expression was found. | ||
if ( | ||
(isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b)) || | ||
(isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b, false)) || | ||
(isStaticBoolean(scope, a) && hasConstantLooseBooleanComparison(scope, b)) | ||
@@ -424,3 +431,3 @@ ) { | ||
if ( | ||
(isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b)) || | ||
(isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b, false)) || | ||
(isStaticBoolean(scope, a) && hasConstantStrictBooleanComparison(scope, b)) | ||
@@ -457,10 +464,12 @@ ) { | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
LogicalExpression(node) { | ||
const { operator, left } = node; | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(node); | ||
if ((operator === "&&" || operator === "||") && isConstant(scope, left, true)) { | ||
context.report({ node: left, messageId: "constantShortCircuit", data: { property: "truthiness", operator } }); | ||
} else if (operator === "??" && hasConstantNullishness(scope, left)) { | ||
} else if (operator === "??" && hasConstantNullishness(scope, left, false)) { | ||
context.report({ node: left, messageId: "constantShortCircuit", data: { property: "nullishness", operator } }); | ||
@@ -470,3 +479,3 @@ } | ||
BinaryExpression(node) { | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(node); | ||
const { right, left, operator } = node; | ||
@@ -473,0 +482,0 @@ const rightConstantOperand = findBinaryExpressionConstantOperand(scope, left, right, operator); |
@@ -51,2 +51,3 @@ /** | ||
loopSetStack = []; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -66,3 +67,3 @@ let loopsInCurrentScope = new Set(); | ||
function trackConstantConditionLoop(node) { | ||
if (node.test && isConstant(context.getScope(), node.test, true)) { | ||
if (node.test && isConstant(sourceCode.getScope(node), node.test, true)) { | ||
loopsInCurrentScope.add(node); | ||
@@ -92,3 +93,3 @@ } | ||
function reportIfConstant(node) { | ||
if (node.test && isConstant(context.getScope(), node.test, true)) { | ||
if (node.test && isConstant(sourceCode.getScope(node), node.test, true)) { | ||
context.report({ node: node.test, messageId: "unexpected" }); | ||
@@ -95,0 +96,0 @@ } |
@@ -8,3 +8,3 @@ /** | ||
const RegExpValidator = require("regexpp").RegExpValidator; | ||
const RegExpValidator = require("@eslint-community/regexpp").RegExpValidator; | ||
const collector = new (class { | ||
@@ -11,0 +11,0 @@ constructor() { |
@@ -18,3 +18,3 @@ /** | ||
docs: { | ||
description: "Disallow division operators explicitly at the beginning of regular expressions", | ||
description: "Disallow equal signs explicitly at the beginning of regular expressions", | ||
recommended: false, | ||
@@ -21,0 +21,0 @@ url: "https://eslint.org/docs/rules/no-div-regex" |
@@ -32,2 +32,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
//-------------------------------------------------------------------------- | ||
@@ -53,3 +55,3 @@ // Helpers | ||
function checkParams(node) { | ||
const variables = context.getDeclaredVariables(node); | ||
const variables = sourceCode.getDeclaredVariables(node); | ||
@@ -56,0 +58,0 @@ for (let i = 0; i < variables.length; ++i) { |
@@ -50,2 +50,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
//-------------------------------------------------------------------------- | ||
@@ -173,21 +175,20 @@ // Helpers | ||
* Display the context report if rule is violated | ||
* @param {Node} node The 'else' node | ||
* @param {Node} elseNode The 'else' node | ||
* @returns {void} | ||
*/ | ||
function displayReport(node) { | ||
const currentScope = context.getScope(); | ||
function displayReport(elseNode) { | ||
const currentScope = sourceCode.getScope(elseNode.parent); | ||
context.report({ | ||
node, | ||
node: elseNode, | ||
messageId: "unexpected", | ||
fix(fixer) { | ||
if (!isSafeFromNameCollisions(node, currentScope)) { | ||
if (!isSafeFromNameCollisions(elseNode, currentScope)) { | ||
return null; | ||
} | ||
const sourceCode = context.getSourceCode(); | ||
const startToken = sourceCode.getFirstToken(node); | ||
const startToken = sourceCode.getFirstToken(elseNode); | ||
const elseToken = sourceCode.getTokenBefore(startToken); | ||
const source = sourceCode.getText(node); | ||
const source = sourceCode.getText(elseNode); | ||
const lastIfToken = sourceCode.getTokenBefore(elseToken); | ||
@@ -208,3 +209,3 @@ let fixedSource, firstTokenOfElseBlock; | ||
*/ | ||
const ifBlockMaybeUnsafe = node.parent.consequent.type !== "BlockStatement" && lastIfToken.value !== ";"; | ||
const ifBlockMaybeUnsafe = elseNode.parent.consequent.type !== "BlockStatement" && lastIfToken.value !== ";"; | ||
const elseBlockUnsafe = /^[([/+`-]/u.test(firstTokenOfElseBlock.value); | ||
@@ -216,3 +217,3 @@ | ||
const endToken = sourceCode.getLastToken(node); | ||
const endToken = sourceCode.getLastToken(elseNode); | ||
const lastTokenOfElseBlock = sourceCode.getTokenBefore(endToken); | ||
@@ -251,4 +252,4 @@ | ||
return new FixTracker(fixer, sourceCode) | ||
.retainEnclosingFunction(node) | ||
.replaceTextRange([elseToken.range[0], node.range[1]], fixedSource); | ||
.retainEnclosingFunction(elseNode) | ||
.replaceTextRange([elseToken.range[0], elseNode.range[1]], fixedSource); | ||
} | ||
@@ -255,0 +256,0 @@ }); |
@@ -75,3 +75,3 @@ /** | ||
/** | ||
* Pushs a `this` scope (non-arrow function, class static block, or class field initializer) information to the stack. | ||
* Pushes a `this` scope (non-arrow function, class static block, or class field initializer) information to the stack. | ||
* Top-level scopes are handled separately. | ||
@@ -88,3 +88,3 @@ * | ||
function enterThisScope(node) { | ||
const strict = context.getScope().isStrict; | ||
const strict = sourceCode.getScope(node).isStrict; | ||
@@ -226,3 +226,3 @@ funcInfo = { | ||
Program(node) { | ||
const scope = context.getScope(), | ||
const scope = sourceCode.getScope(node), | ||
features = context.parserOptions.ecmaFeatures || {}, | ||
@@ -245,4 +245,4 @@ strict = | ||
"Program:exit"() { | ||
const globalScope = context.getScope(); | ||
"Program:exit"(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
@@ -249,0 +249,0 @@ exitThisScope(); |
@@ -34,2 +34,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -48,3 +50,3 @@ * Finds and reports references that are non initializer and writable. | ||
CatchClause(node) { | ||
context.getDeclaredVariables(node).forEach(checkVariable); | ||
sourceCode.getDeclaredVariables(node).forEach(checkVariable); | ||
} | ||
@@ -51,0 +53,0 @@ }; |
@@ -54,2 +54,3 @@ /** | ||
const config = context.options[0] || {}; | ||
const sourceCode = context.getSourceCode(); | ||
const exceptions = new Set(config.exceptions || []); | ||
@@ -163,4 +164,4 @@ const modifiedBuiltins = new Set( | ||
"Program:exit"() { | ||
const globalScope = context.getScope(); | ||
"Program:exit"(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
@@ -167,0 +168,0 @@ modifiedBuiltins.forEach(builtin => { |
@@ -13,3 +13,3 @@ /** | ||
const astUtils = require("./utils/ast-utils"); | ||
const eslintUtils = require("eslint-utils"); | ||
const eslintUtils = require("@eslint-community/eslint-utils"); | ||
@@ -16,0 +16,0 @@ const precedence = astUtils.getPrecedence; |
@@ -11,3 +11,3 @@ /** | ||
const { isParenthesized: isParenthesizedRaw } = require("eslint-utils"); | ||
const { isParenthesized: isParenthesizedRaw } = require("@eslint-community/eslint-utils"); | ||
const astUtils = require("./utils/ast-utils.js"); | ||
@@ -770,2 +770,34 @@ | ||
/** | ||
* Checks if the left-hand side of an assignment is an identifier, the operator is one of | ||
* `=`, `&&=`, `||=` or `??=` and the right-hand side is an anonymous class or function. | ||
* | ||
* As per https://tc39.es/ecma262/#sec-assignment-operators-runtime-semantics-evaluation, an | ||
* assignment involving one of the operators `=`, `&&=`, `||=` or `??=` where the right-hand | ||
* side is an anonymous class or function and the left-hand side is an *unparenthesized* | ||
* identifier has different semantics than other assignments. | ||
* Specifically, when an expression like `foo = function () {}` is evaluated, `foo.name` | ||
* will be set to the string "foo", i.e. the identifier name. The same thing does not happen | ||
* when evaluating `(foo) = function () {}`. | ||
* Since the parenthesizing of the identifier in the left-hand side is significant in this | ||
* special case, the parentheses, if present, should not be flagged as unnecessary. | ||
* @param {ASTNode} node an AssignmentExpression node. | ||
* @returns {boolean} `true` if the left-hand side of the assignment is an identifier, the | ||
* operator is one of `=`, `&&=`, `||=` or `??=` and the right-hand side is an anonymous | ||
* class or function; otherwise, `false`. | ||
*/ | ||
function isAnonymousFunctionAssignmentException({ left, operator, right }) { | ||
if (left.type === "Identifier" && ["=", "&&=", "||=", "??="].includes(operator)) { | ||
const rhsType = right.type; | ||
if (rhsType === "ArrowFunctionExpression") { | ||
return true; | ||
} | ||
if ((rhsType === "FunctionExpression" || rhsType === "ClassExpression") && !right.id) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
return { | ||
@@ -809,3 +841,4 @@ ArrayExpression(node) { | ||
AssignmentExpression(node) { | ||
if (canBeAssignmentTarget(node.left) && hasExcessParens(node.left)) { | ||
if (canBeAssignmentTarget(node.left) && hasExcessParens(node.left) && | ||
(!isAnonymousFunctionAssignmentException(node) || isParenthesisedTwice(node.left))) { | ||
report(node.left); | ||
@@ -812,0 +845,0 @@ } |
@@ -34,2 +34,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -69,3 +71,3 @@ * Reports a reference if is non initializer and writable. | ||
function checkForFunction(node) { | ||
context.getDeclaredVariables(node).forEach(checkVariable); | ||
sourceCode.getDeclaredVariables(node).forEach(checkVariable); | ||
} | ||
@@ -72,0 +74,0 @@ |
@@ -44,2 +44,3 @@ /** | ||
const config = context.options[0]; | ||
const sourceCode = context.getSourceCode(); | ||
const exceptions = (config && config.exceptions) || []; | ||
@@ -88,4 +89,4 @@ | ||
return { | ||
Program() { | ||
const globalScope = context.getScope(); | ||
Program(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
@@ -92,0 +93,0 @@ globalScope.variables.forEach(checkVariable); |
@@ -46,2 +46,3 @@ /** | ||
const checkLexicalBindings = context.options[0] && context.options[0].lexicalBindings === true; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -66,4 +67,4 @@ /** | ||
return { | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
@@ -70,0 +71,0 @@ scope.variables.forEach(variable => { |
@@ -13,3 +13,3 @@ /** | ||
const astUtils = require("./utils/ast-utils"); | ||
const { getStaticValue } = require("eslint-utils"); | ||
const { getStaticValue } = require("@eslint-community/eslint-utils"); | ||
@@ -41,2 +41,3 @@ //------------------------------------------------------------------------------ | ||
const EVAL_LIKE_FUNC_PATTERN = /^(?:set(?:Interval|Timeout)|execScript)$/u; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -71,3 +72,3 @@ /** | ||
const staticValue = getStaticValue(firstArgument, context.getScope()); | ||
const staticValue = getStaticValue(firstArgument, sourceCode.getScope(node)); | ||
const isStaticString = staticValue && typeof staticValue.value === "string"; | ||
@@ -123,4 +124,4 @@ const isString = isStaticString || isEvaluatedString(firstArgument); | ||
}, | ||
"Program:exit"() { | ||
const globalScope = context.getScope(); | ||
"Program:exit"(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
@@ -127,0 +128,0 @@ GLOBAL_CANDIDATES |
@@ -12,3 +12,3 @@ /** | ||
const { findVariable } = require("eslint-utils"); | ||
const { findVariable } = require("@eslint-community/eslint-utils"); | ||
const astUtils = require("./utils/ast-utils"); | ||
@@ -198,7 +198,9 @@ | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
ImportDeclaration(node) { | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(node); | ||
for (const variable of context.getDeclaredVariables(node)) { | ||
for (const variable of sourceCode.getDeclaredVariables(node)) { | ||
const shouldCheckMembers = variable.defs.some( | ||
@@ -205,0 +207,0 @@ d => d.node.type === "ImportNamespaceSpecifier" |
@@ -11,3 +11,3 @@ /** | ||
const RegExpValidator = require("regexpp").RegExpValidator; | ||
const RegExpValidator = require("@eslint-community/regexpp").RegExpValidator; | ||
const validator = new RegExpValidator(); | ||
@@ -14,0 +14,0 @@ const validFlags = /[dgimsuy]/gu; |
@@ -98,3 +98,3 @@ /** | ||
if (codePath.origin === "program") { | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(node); | ||
const features = context.parserOptions.ecmaFeatures || {}; | ||
@@ -124,3 +124,3 @@ | ||
stack.push({ | ||
init: !context.getScope().isStrict, | ||
init: !sourceCode.getScope(node).isStrict, | ||
node, | ||
@@ -127,0 +127,0 @@ valid: true |
@@ -37,2 +37,3 @@ /** | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
@@ -63,3 +64,3 @@ //-------------------------------------------------------------------------- | ||
// Fetch the innermost scope. | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(node); | ||
@@ -66,0 +67,0 @@ /* |
@@ -36,2 +36,3 @@ /** | ||
let ruleDef; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -71,5 +72,6 @@ /** | ||
* and "marks it" as valid if any. | ||
* @param {ASTNode} node The current node to check. | ||
* @returns {void} | ||
*/ | ||
function markLoneBlock() { | ||
function markLoneBlock(node) { | ||
if (loneBlocks.length === 0) { | ||
@@ -79,3 +81,3 @@ return; | ||
const block = context.getAncestors().pop(); | ||
const block = sourceCode.getAncestors(node).pop(); | ||
@@ -122,9 +124,9 @@ if (loneBlocks[loneBlocks.length - 1] === block) { | ||
if (node.kind === "let" || node.kind === "const") { | ||
markLoneBlock(); | ||
markLoneBlock(node); | ||
} | ||
}; | ||
ruleDef.FunctionDeclaration = function() { | ||
if (context.getScope().isStrict) { | ||
markLoneBlock(); | ||
ruleDef.FunctionDeclaration = function(node) { | ||
if (sourceCode.getScope(node).isStrict) { | ||
markLoneBlock(node); | ||
} | ||
@@ -131,0 +133,0 @@ }; |
@@ -35,3 +35,3 @@ /** | ||
IfStatement(node) { | ||
const ancestors = context.getAncestors(), | ||
const ancestors = sourceCode.getAncestors(node), | ||
parent = ancestors.pop(), | ||
@@ -38,0 +38,0 @@ grandparent = ancestors.pop(); |
@@ -171,2 +171,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -187,3 +189,3 @@ * Reports functions which match the following condition: | ||
const references = context.getScope().through; | ||
const references = sourceCode.getScope(node).through; | ||
const unsafeRefs = references.filter(r => !isSafe(loopNode, r)).map(r => r.identifier.name); | ||
@@ -190,0 +192,0 @@ |
@@ -6,6 +6,7 @@ /** | ||
const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("eslint-utils"); | ||
const { RegExpValidator, RegExpParser, visitRegExpAST } = require("regexpp"); | ||
const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("@eslint-community/eslint-utils"); | ||
const { RegExpParser, visitRegExpAST } = require("@eslint-community/regexpp"); | ||
const { isCombiningCharacter, isEmojiModifier, isRegionalIndicatorSymbol, isSurrogatePair } = require("./utils/unicode"); | ||
const astUtils = require("./utils/ast-utils.js"); | ||
const { isValidWithUnicodeFlag } = require("./utils/regular-expressions"); | ||
@@ -16,4 +17,2 @@ //------------------------------------------------------------------------------ | ||
const REGEXPP_LATEST_ECMA_VERSION = 2022; | ||
/** | ||
@@ -190,34 +189,6 @@ * Iterate character sequences of a given nodes. | ||
/** | ||
* Checks if the given regular expression pattern would be valid with the `u` flag. | ||
* @param {string} pattern The regular expression pattern to verify. | ||
* @returns {boolean} `true` if the pattern would be valid with the `u` flag. | ||
* `false` if the pattern would be invalid with the `u` flag or the configured | ||
* ecmaVersion doesn't support the `u` flag. | ||
*/ | ||
function isValidWithUnicodeFlag(pattern) { | ||
const { ecmaVersion } = context.languageOptions; | ||
// ecmaVersion <= 5 doesn't support the 'u' flag | ||
if (ecmaVersion <= 5) { | ||
return false; | ||
} | ||
const validator = new RegExpValidator({ | ||
ecmaVersion: Math.min(ecmaVersion, REGEXPP_LATEST_ECMA_VERSION) | ||
}); | ||
try { | ||
validator.validatePattern(pattern, void 0, void 0, /* uFlag = */ true); | ||
} catch { | ||
return false; | ||
} | ||
return true; | ||
} | ||
return { | ||
"Literal[regex]"(node) { | ||
verify(node, node.regex.pattern, node.regex.flags, fixer => { | ||
if (!isValidWithUnicodeFlag(node.regex.pattern)) { | ||
if (!isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, node.regex.pattern)) { | ||
return null; | ||
@@ -229,4 +200,4 @@ } | ||
}, | ||
"Program"() { | ||
const scope = context.getScope(); | ||
"Program"(node) { | ||
const scope = sourceCode.getScope(node); | ||
const tracker = new ReferenceTracker(scope); | ||
@@ -239,6 +210,6 @@ | ||
*/ | ||
for (const { node } of tracker.iterateGlobalReferences({ | ||
for (const { node: refNode } of tracker.iterateGlobalReferences({ | ||
RegExp: { [CALL]: true, [CONSTRUCT]: true } | ||
})) { | ||
const [patternNode, flagsNode] = node.arguments; | ||
const [patternNode, flagsNode] = refNode.arguments; | ||
const pattern = getStringIfConstant(patternNode, scope); | ||
@@ -248,10 +219,10 @@ const flags = getStringIfConstant(flagsNode, scope); | ||
if (typeof pattern === "string") { | ||
verify(node, pattern, flags || "", fixer => { | ||
verify(refNode, pattern, flags || "", fixer => { | ||
if (!isValidWithUnicodeFlag(pattern)) { | ||
if (!isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, pattern)) { | ||
return null; | ||
} | ||
if (node.arguments.length === 1) { | ||
const penultimateToken = sourceCode.getLastToken(node, { skip: 1 }); // skip closing parenthesis | ||
if (refNode.arguments.length === 1) { | ||
const penultimateToken = sourceCode.getLastToken(refNode, { skip: 1 }); // skip closing parenthesis | ||
@@ -258,0 +229,0 @@ return fixer.insertTextAfter( |
@@ -50,2 +50,3 @@ /** | ||
const exceptions = (config && config.exceptions) || []; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -91,4 +92,4 @@ /** | ||
return { | ||
Program() { | ||
const globalScope = context.getScope(); | ||
Program(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
@@ -95,0 +96,0 @@ globalScope.variables.forEach(checkVariable); |
@@ -43,6 +43,7 @@ /** | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
"Program:exit"() { | ||
const globalScope = context.getScope(); | ||
"Program:exit"(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
const variable = globalScope.set.get("Function"); | ||
@@ -52,8 +53,8 @@ | ||
variable.references.forEach(ref => { | ||
const node = ref.identifier; | ||
const { parent } = node; | ||
const idNode = ref.identifier; | ||
const { parent } = idNode; | ||
let evalNode; | ||
if (parent) { | ||
if (node === parent.callee && ( | ||
if (idNode === parent.callee && ( | ||
parent.type === "NewExpression" || | ||
@@ -65,3 +66,3 @@ parent.type === "CallExpression" | ||
parent.type === "MemberExpression" && | ||
node === parent.object && | ||
idNode === parent.object && | ||
callMethods.has(astUtils.getStaticPropertyName(parent)) | ||
@@ -68,0 +69,0 @@ ) { |
@@ -38,5 +38,7 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
"Program:exit"() { | ||
const globalScope = context.getScope(); | ||
"Program:exit"(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
@@ -48,8 +50,8 @@ for (const nonConstructorName of nonConstructorGlobalFunctionNames) { | ||
variable.references.forEach(ref => { | ||
const node = ref.identifier; | ||
const parent = node.parent; | ||
const idNode = ref.identifier; | ||
const parent = idNode.parent; | ||
if (parent && parent.type === "NewExpression" && parent.callee === node) { | ||
if (parent && parent.type === "NewExpression" && parent.callee === idNode) { | ||
context.report({ | ||
node, | ||
node: idNode, | ||
messageId: "noNewNonconstructor", | ||
@@ -56,0 +58,0 @@ data: { name: nonConstructorName } |
@@ -37,6 +37,9 @@ /** | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
NewExpression(node) { | ||
const variable = astUtils.getVariableByName( | ||
context.getScope(), | ||
sourceCode.getScope(node), | ||
node.callee.name | ||
@@ -43,0 +46,0 @@ ); |
@@ -32,5 +32,7 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
"Program:exit"() { | ||
const globalScope = context.getScope(); | ||
"Program:exit"(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
const variable = globalScope.set.get("Symbol"); | ||
@@ -40,8 +42,8 @@ | ||
variable.references.forEach(ref => { | ||
const node = ref.identifier; | ||
const parent = node.parent; | ||
const idNode = ref.identifier; | ||
const parent = idNode.parent; | ||
if (parent && parent.type === "NewExpression" && parent.callee === node) { | ||
if (parent && parent.type === "NewExpression" && parent.callee === idNode) { | ||
context.report({ | ||
node, | ||
node: idNode, | ||
messageId: "noNewSymbol" | ||
@@ -48,0 +50,0 @@ }); |
@@ -12,3 +12,3 @@ /** | ||
const { CALL, CONSTRUCT, ReferenceTracker } = require("eslint-utils"); | ||
const { CALL, CONSTRUCT, ReferenceTracker } = require("@eslint-community/eslint-utils"); | ||
const getPropertyName = require("./utils/ast-utils").getStaticPropertyName; | ||
@@ -62,5 +62,7 @@ | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
const tracker = new ReferenceTracker(scope); | ||
@@ -76,8 +78,8 @@ const traceMap = {}; | ||
for (const { node, path } of tracker.iterateGlobalReferences(traceMap)) { | ||
const name = getReportNodeName(node.callee); | ||
for (const { node: refNode, path } of tracker.iterateGlobalReferences(traceMap)) { | ||
const name = getReportNodeName(refNode.callee); | ||
const ref = path[0]; | ||
const messageId = name === ref ? "unexpectedCall" : "unexpectedRefCall"; | ||
context.report({ node, messageId, data: { name, ref } }); | ||
context.report({ node: refNode, messageId, data: { name, ref } }); | ||
} | ||
@@ -84,0 +86,0 @@ } |
@@ -73,2 +73,3 @@ /** | ||
const ignoredPropertyAssignmentsForRegex = context.options[0] && context.options[0].ignorePropertyModificationsForRegex || []; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -218,3 +219,3 @@ /** | ||
function checkForFunction(node) { | ||
context.getDeclaredVariables(node).forEach(checkVariable); | ||
sourceCode.getDeclaredVariables(node).forEach(checkVariable); | ||
} | ||
@@ -221,0 +222,0 @@ |
@@ -12,3 +12,3 @@ /** | ||
const { findVariable } = require("eslint-utils"); | ||
const { findVariable } = require("@eslint-community/eslint-utils"); | ||
@@ -88,2 +88,3 @@ //------------------------------------------------------------------------------ | ||
let funcInfo = null; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -104,3 +105,3 @@ /** | ||
upper: funcInfo, | ||
shouldCheck: functionTypesToCheck.has(node.type) && isPromiseExecutor(node, context.getScope()) | ||
shouldCheck: functionTypesToCheck.has(node.type) && isPromiseExecutor(node, sourceCode.getScope(node)) | ||
}; | ||
@@ -107,0 +108,0 @@ |
@@ -132,3 +132,3 @@ /** | ||
function checkForBlock(node) { | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(node); | ||
@@ -145,4 +145,4 @@ /* | ||
return { | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
@@ -149,0 +149,0 @@ findVariablesInScope(scope); |
@@ -13,3 +13,3 @@ /** | ||
const astUtils = require("./utils/ast-utils"); | ||
const regexpp = require("regexpp"); | ||
const regexpp = require("@eslint-community/regexpp"); | ||
@@ -58,2 +58,4 @@ //------------------------------------------------------------------------------ | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -154,3 +156,3 @@ * Validate regular expression | ||
function checkFunction(node) { | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(node); | ||
const regExpVar = astUtils.getVariableByName(scope, "RegExp"); | ||
@@ -157,0 +159,0 @@ const shadowed = regExpVar && regExpVar.defs.length > 0; |
@@ -102,2 +102,3 @@ /** | ||
const restrictDefaultExports = context.options[0] && context.options[0].restrictDefaultExports; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -180,3 +181,3 @@ /** | ||
} else if (declaration.type === "VariableDeclaration") { | ||
context.getDeclaredVariables(declaration) | ||
sourceCode.getDeclaredVariables(declaration) | ||
.map(v => v.defs.find(d => d.parent === declaration)) | ||
@@ -183,0 +184,0 @@ .map(d => d.name) // Identifier nodes |
@@ -53,2 +53,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
// If no globals are restricted, we don't need to do anything | ||
@@ -103,4 +105,4 @@ if (context.options.length === 0) { | ||
return { | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
@@ -107,0 +109,0 @@ // Report variables declared elsewhere (ex: variables defined as "global" by eslint) |
@@ -13,3 +13,3 @@ /** | ||
const astUtils = require("./utils/ast-utils"); | ||
const { findVariable } = require("eslint-utils"); | ||
const { findVariable } = require("@eslint-community/eslint-utils"); | ||
@@ -160,2 +160,3 @@ //------------------------------------------------------------------------------ | ||
let funcInfo = null; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -168,3 +169,3 @@ /** | ||
function enterFunction(node) { | ||
const outerScope = getOuterScope(context.getScope()); | ||
const outerScope = getOuterScope(sourceCode.getScope(node)); | ||
@@ -171,0 +172,0 @@ funcInfo = { |
@@ -46,6 +46,7 @@ /** | ||
const RESTRICTED = new Set(["undefined", "NaN", "Infinity", "arguments", "eval"]); | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
"VariableDeclaration, :function, CatchClause"(node) { | ||
for (const variable of context.getDeclaredVariables(node)) { | ||
for (const variable of sourceCode.getDeclaredVariables(node)) { | ||
if (variable.defs.length > 0 && RESTRICTED.has(variable.name) && !safelyShadowsUndefined(variable)) { | ||
@@ -52,0 +53,0 @@ context.report({ |
@@ -70,2 +70,3 @@ /** | ||
}; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -322,4 +323,4 @@ /** | ||
return { | ||
"Program:exit"() { | ||
const globalScope = context.getScope(); | ||
"Program:exit"(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
const stack = globalScope.childScopes.slice(); | ||
@@ -326,0 +327,0 @@ |
@@ -42,3 +42,3 @@ /** | ||
init = node.init && node.init.name, | ||
scope = context.getScope(), | ||
scope = sourceCode.getScope(node), | ||
undefinedVar = astUtils.getVariableByName(scope, "undefined"), | ||
@@ -45,0 +45,0 @@ shadowed = undefinedVar && undefinedVar.defs.length > 0, |
@@ -57,6 +57,7 @@ /** | ||
const considerTypeOf = options && options.typeof === true || false; | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
"Program:exit"(/* node */) { | ||
const globalScope = context.getScope(); | ||
"Program:exit"(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
@@ -63,0 +64,0 @@ globalScope.through.forEach(ref => { |
@@ -31,2 +31,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -70,4 +72,4 @@ * Report an invalid "undefined" identifier node. | ||
return { | ||
"Program:exit"() { | ||
const globalScope = context.getScope(); | ||
"Program:exit"(node) { | ||
const globalScope = sourceCode.getScope(node); | ||
@@ -74,0 +76,0 @@ const stack = [globalScope]; |
@@ -87,2 +87,3 @@ /** | ||
const allowInObjectDestructuring = typeof options.allowInObjectDestructuring !== "undefined" ? options.allowInObjectDestructuring : true; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -217,3 +218,3 @@ //------------------------------------------------------------------------- | ||
function checkForDanglingUnderscoreInVariableExpression(node) { | ||
context.getDeclaredVariables(node).forEach(variable => { | ||
sourceCode.getDeclaredVariables(node).forEach(variable => { | ||
const definition = variable.defs.find(def => def.node === node); | ||
@@ -220,0 +221,0 @@ const identifierNode = definition.name; |
@@ -343,4 +343,4 @@ /** | ||
return { | ||
"Program:exit"() { | ||
const queue = [context.getScope()]; | ||
"Program:exit"(node) { | ||
const queue = [sourceCode.getScope(node)]; | ||
@@ -347,0 +347,0 @@ groupMap = new Map(); |
@@ -73,3 +73,4 @@ /** | ||
allowTaggedTemplates = config.allowTaggedTemplates || false, | ||
enforceForJSX = config.enforceForJSX || false; | ||
enforceForJSX = config.enforceForJSX || false, | ||
sourceCode = context.getSourceCode(); | ||
@@ -184,3 +185,3 @@ /** | ||
ExpressionStatement(node) { | ||
if (Checker.isDisallowed(node.expression) && !isDirective(node, context.getAncestors())) { | ||
if (Checker.isDisallowed(node.expression) && !isDirective(node, sourceCode.getAncestors(node))) { | ||
context.report({ node, messageId: "unusedExpression" }); | ||
@@ -187,0 +188,0 @@ } |
@@ -558,3 +558,3 @@ /** | ||
const def = variable.defs[0]; | ||
const params = context.getDeclaredVariables(def.node); | ||
const params = sourceCode.getDeclaredVariables(def.node); | ||
const posteriorParams = params.slice(params.indexOf(variable) + 1); | ||
@@ -677,3 +677,3 @@ | ||
"Program:exit"(programNode) { | ||
const unusedVars = collectUnusedVariables(context.getScope(), []); | ||
const unusedVars = collectUnusedVariables(sourceCode.getScope(programNode), []); | ||
@@ -680,0 +680,0 @@ for (let i = 0, l = unusedVars.length; i < l; ++i) { |
@@ -261,2 +261,3 @@ /** | ||
const options = parseOptions(context.options[0]); | ||
const sourceCode = context.getSourceCode(); | ||
@@ -343,4 +344,4 @@ /** | ||
return { | ||
Program() { | ||
checkReferencesInScope(context.getScope()); | ||
Program(node) { | ||
checkReferencesInScope(sourceCode.getScope(node)); | ||
} | ||
@@ -347,0 +348,0 @@ }; |
@@ -12,4 +12,4 @@ /** | ||
const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("eslint-utils"); | ||
const { RegExpParser, visitRegExpAST } = require("regexpp"); | ||
const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("@eslint-community/eslint-utils"); | ||
const { RegExpParser, visitRegExpAST } = require("@eslint-community/regexpp"); | ||
@@ -86,2 +86,4 @@ //------------------------------------------------------------------------------ | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -172,4 +174,4 @@ * Checks and reports useless backreferences in the given regular expression. | ||
}, | ||
Program() { | ||
const scope = context.getScope(), | ||
Program(node) { | ||
const scope = sourceCode.getScope(node), | ||
tracker = new ReferenceTracker(scope), | ||
@@ -183,4 +185,4 @@ traceMap = { | ||
for (const { node } of tracker.iterateGlobalReferences(traceMap)) { | ||
const [patternNode, flagsNode] = node.arguments, | ||
for (const { node: refNode } of tracker.iterateGlobalReferences(traceMap)) { | ||
const [patternNode, flagsNode] = refNode.arguments, | ||
pattern = getStringIfConstant(patternNode, scope), | ||
@@ -190,3 +192,3 @@ flags = getStringIfConstant(flagsNode, scope); | ||
if (typeof pattern === "string") { | ||
checkRegex(node, pattern, flags || ""); | ||
checkRegex(refNode, pattern, flags || ""); | ||
} | ||
@@ -193,0 +195,0 @@ } |
@@ -200,3 +200,3 @@ /** | ||
// Makes and pushs a new scope information. | ||
// Makes and pushes a new scope information. | ||
onCodePathStart(codePath) { | ||
@@ -203,0 +203,0 @@ scopeInfo = { |
@@ -213,3 +213,3 @@ /** | ||
} | ||
const variables = context.getDeclaredVariables(declarator); | ||
const variables = sourceCode.getDeclaredVariables(declarator); | ||
@@ -272,3 +272,3 @@ return variables.some(hasReferenceInTDZ(declarator.init)); | ||
function canFix(node) { | ||
const variables = context.getDeclaredVariables(node); | ||
const variables = sourceCode.getDeclaredVariables(node); | ||
const scopeNode = getScopeNode(node); | ||
@@ -275,0 +275,0 @@ |
@@ -357,7 +357,8 @@ /** | ||
* Also, this marks all `arguments` identifiers so that they can be detected later. | ||
* @param {ASTNode} node The node representing the function. | ||
* @returns {void} | ||
*/ | ||
function enterFunction() { | ||
function enterFunction(node) { | ||
lexicalScopeStack.unshift(new Set()); | ||
context.getScope().variables.filter(variable => variable.name === "arguments").forEach(variable => { | ||
sourceCode.getScope(node).variables.filter(variable => variable.name === "arguments").forEach(variable => { | ||
variable.references.map(ref => ref.identifier).forEach(identifier => argumentsIdentifiers.add(identifier)); | ||
@@ -364,0 +365,0 @@ }); |
@@ -266,3 +266,3 @@ /** | ||
// Skip recursive functions. | ||
const nameVar = context.getDeclaredVariables(node)[0]; | ||
const nameVar = sourceCode.getDeclaredVariables(node)[0]; | ||
@@ -274,3 +274,3 @@ if (isFunctionName(nameVar) && nameVar.references.length > 0) { | ||
// Skip if it's using arguments. | ||
const variable = getVariableOfArguments(context.getScope()); | ||
const variable = getVariableOfArguments(sourceCode.getScope(node)); | ||
@@ -277,0 +277,0 @@ if (variable && variable.references.length > 0) { |
@@ -496,3 +496,3 @@ /** | ||
if (node.kind === "let" && !isInitOfForStatement(node)) { | ||
variables.push(...context.getDeclaredVariables(node)); | ||
variables.push(...sourceCode.getDeclaredVariables(node)); | ||
} | ||
@@ -499,0 +499,0 @@ } |
@@ -13,3 +13,3 @@ /** | ||
const astUtils = require("./utils/ast-utils"); | ||
const { CALL, ReferenceTracker } = require("eslint-utils"); | ||
const { CALL, ReferenceTracker } = require("@eslint-community/eslint-utils"); | ||
@@ -176,4 +176,4 @@ //------------------------------------------------------------------------------ | ||
return { | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
const tracker = new ReferenceTracker(scope); | ||
@@ -186,4 +186,4 @@ const trackMap = { | ||
for (const { node } of tracker.iterateGlobalReferences(trackMap)) { | ||
report(node); | ||
for (const { node: refNode } of tracker.iterateGlobalReferences(trackMap)) { | ||
report(refNode); | ||
} | ||
@@ -190,0 +190,0 @@ } |
@@ -17,4 +17,4 @@ /** | ||
getStringIfConstant | ||
} = require("eslint-utils"); | ||
const regexpp = require("regexpp"); | ||
} = require("@eslint-community/eslint-utils"); | ||
const regexpp = require("@eslint-community/regexpp"); | ||
@@ -155,4 +155,4 @@ //------------------------------------------------------------------------------ | ||
}, | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
const tracker = new ReferenceTracker(scope); | ||
@@ -166,8 +166,8 @@ const traceMap = { | ||
for (const { node } of tracker.iterateGlobalReferences(traceMap)) { | ||
const regex = getStringIfConstant(node.arguments[0]); | ||
const flags = getStringIfConstant(node.arguments[1]); | ||
for (const { node: refNode } of tracker.iterateGlobalReferences(traceMap)) { | ||
const regex = getStringIfConstant(refNode.arguments[0]); | ||
const flags = getStringIfConstant(refNode.arguments[1]); | ||
if (regex) { | ||
checkRegex(regex, node, node.arguments[0], flags && flags.includes("u")); | ||
checkRegex(regex, refNode, refNode.arguments[0], flags && flags.includes("u")); | ||
} | ||
@@ -174,0 +174,0 @@ } |
@@ -64,2 +64,5 @@ /** | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
@@ -76,3 +79,3 @@ CallExpression(node) { | ||
// check `Object` scope | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(node); | ||
const variable = astUtils.getVariableByName(scope, "Object"); | ||
@@ -90,3 +93,2 @@ | ||
fix(fixer) { | ||
const sourceCode = context.getSourceCode(); | ||
@@ -93,0 +95,0 @@ if (sourceCode.getCommentsInside(node.callee).length > 0) { |
@@ -9,3 +9,3 @@ /** | ||
const { CALL, ReferenceTracker } = require("eslint-utils"); | ||
const { CALL, ReferenceTracker } = require("@eslint-community/eslint-utils"); | ||
const { | ||
@@ -269,4 +269,4 @@ isCommaToken, | ||
return { | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
const tracker = new ReferenceTracker(scope); | ||
@@ -280,18 +280,18 @@ const trackMap = { | ||
// Iterate all calls of `Object.assign` (only of the global variable `Object`). | ||
for (const { node } of tracker.iterateGlobalReferences(trackMap)) { | ||
for (const { node: refNode } of tracker.iterateGlobalReferences(trackMap)) { | ||
if ( | ||
node.arguments.length >= 1 && | ||
node.arguments[0].type === "ObjectExpression" && | ||
!hasArraySpread(node) && | ||
refNode.arguments.length >= 1 && | ||
refNode.arguments[0].type === "ObjectExpression" && | ||
!hasArraySpread(refNode) && | ||
!( | ||
node.arguments.length > 1 && | ||
hasArgumentsWithAccessors(node) | ||
refNode.arguments.length > 1 && | ||
hasArgumentsWithAccessors(refNode) | ||
) | ||
) { | ||
const messageId = node.arguments.length === 1 | ||
const messageId = refNode.arguments.length === 1 | ||
? "useLiteralMessage" | ||
: "useSpreadMessage"; | ||
const fix = defineFixer(node, sourceCode); | ||
const fix = defineFixer(refNode, sourceCode); | ||
context.report({ node, messageId, fix }); | ||
context.report({ node: refNode, messageId, fix }); | ||
} | ||
@@ -298,0 +298,0 @@ } |
@@ -44,2 +44,3 @@ /** | ||
const ALLOW_EMPTY_REJECT = context.options.length && context.options[0].allowEmptyReject; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -104,3 +105,3 @@ //---------------------------------------------------------------------- | ||
) { | ||
context.getDeclaredVariables(node.arguments[0]) | ||
sourceCode.getDeclaredVariables(node.arguments[0]) | ||
@@ -107,0 +108,0 @@ /* |
@@ -13,5 +13,6 @@ /** | ||
const astUtils = require("./utils/ast-utils"); | ||
const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("eslint-utils"); | ||
const { RegExpValidator, visitRegExpAST, RegExpParser } = require("regexpp"); | ||
const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("@eslint-community/eslint-utils"); | ||
const { RegExpValidator, visitRegExpAST, RegExpParser } = require("@eslint-community/regexpp"); | ||
const { canTokensBeAdjacent } = require("./utils/ast-utils"); | ||
const { REGEXPP_LATEST_ECMA_VERSION } = require("./utils/regular-expressions"); | ||
@@ -22,4 +23,2 @@ //------------------------------------------------------------------------------ | ||
const REGEXPP_LATEST_ECMA_VERSION = 2022; | ||
/** | ||
@@ -168,3 +167,3 @@ * Determines whether the given node is a string literal. | ||
function isGlobalReference(node) { | ||
const scope = context.getScope(); | ||
const scope = sourceCode.getScope(node); | ||
const variable = findVariable(scope, node); | ||
@@ -381,4 +380,4 @@ | ||
return { | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
const tracker = new ReferenceTracker(scope); | ||
@@ -392,12 +391,12 @@ const traceMap = { | ||
for (const { node } of tracker.iterateGlobalReferences(traceMap)) { | ||
if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(node)) { | ||
const regexNode = node.arguments[0]; | ||
for (const { node: refNode } of tracker.iterateGlobalReferences(traceMap)) { | ||
if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(refNode)) { | ||
const regexNode = refNode.arguments[0]; | ||
if (node.arguments.length === 2) { | ||
if (refNode.arguments.length === 2) { | ||
const suggests = []; | ||
const argFlags = getStringValue(node.arguments[1]) || ""; | ||
const argFlags = getStringValue(refNode.arguments[1]) || ""; | ||
if (canFixTo(node, regexNode.regex.pattern, argFlags)) { | ||
if (canFixTo(refNode, regexNode.regex.pattern, argFlags)) { | ||
suggests.push({ | ||
@@ -415,3 +414,3 @@ messageId: "replaceWithLiteralAndFlags", | ||
!areFlagsEqual(mergedFlags, argFlags) && | ||
canFixTo(node, regexNode.regex.pattern, mergedFlags) | ||
canFixTo(refNode, regexNode.regex.pattern, mergedFlags) | ||
) { | ||
@@ -426,3 +425,3 @@ suggests.push({ | ||
context.report({ | ||
node, | ||
node: refNode, | ||
messageId: "unexpectedRedundantRegExpWithFlags", | ||
@@ -435,3 +434,3 @@ suggest: suggests.map(({ flags, pattern, messageId }) => ({ | ||
fix(fixer) { | ||
return fixer.replaceText(node, getSafeOutput(node, `/${pattern}/${flags}`)); | ||
return fixer.replaceText(refNode, getSafeOutput(refNode, `/${pattern}/${flags}`)); | ||
} | ||
@@ -443,3 +442,3 @@ })) | ||
if (canFixTo(node, regexNode.regex.pattern, regexNode.regex.flags)) { | ||
if (canFixTo(refNode, regexNode.regex.pattern, regexNode.regex.flags)) { | ||
outputs.push(sourceCode.getText(regexNode)); | ||
@@ -450,3 +449,3 @@ } | ||
context.report({ | ||
node, | ||
node: refNode, | ||
messageId: "unexpectedRedundantRegExp", | ||
@@ -457,4 +456,4 @@ suggest: outputs.map(output => ({ | ||
return fixer.replaceText( | ||
node, | ||
getSafeOutput(node, output) | ||
refNode, | ||
getSafeOutput(refNode, output) | ||
); | ||
@@ -465,12 +464,12 @@ } | ||
} | ||
} else if (hasOnlyStaticStringArguments(node)) { | ||
let regexContent = getStringValue(node.arguments[0]); | ||
} else if (hasOnlyStaticStringArguments(refNode)) { | ||
let regexContent = getStringValue(refNode.arguments[0]); | ||
let noFix = false; | ||
let flags; | ||
if (node.arguments[1]) { | ||
flags = getStringValue(node.arguments[1]); | ||
if (refNode.arguments[1]) { | ||
flags = getStringValue(refNode.arguments[1]); | ||
} | ||
if (!canFixTo(node, regexContent, flags)) { | ||
if (!canFixTo(refNode, regexContent, flags)) { | ||
noFix = true; | ||
@@ -509,3 +508,3 @@ } | ||
context.report({ | ||
node, | ||
node: refNode, | ||
messageId: "unexpectedRegExp", | ||
@@ -515,3 +514,3 @@ suggest: noFix ? [] : [{ | ||
fix(fixer) { | ||
return fixer.replaceText(node, getSafeOutput(node, newRegExpValue)); | ||
return fixer.replaceText(refNode, getSafeOutput(refNode, newRegExpValue)); | ||
} | ||
@@ -518,0 +517,0 @@ }] |
@@ -82,2 +82,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -98,6 +100,7 @@ * Reports a given reference. | ||
* Reports references of the implicit `arguments` variable if exist. | ||
* @param {ASTNode} node The node representing the function. | ||
* @returns {void} | ||
*/ | ||
function checkForArguments() { | ||
const argumentsVar = getVariableOfArguments(context.getScope()); | ||
function checkForArguments(node) { | ||
const argumentsVar = getVariableOfArguments(sourceCode.getScope(node)); | ||
@@ -104,0 +107,0 @@ if (argumentsVar) { |
@@ -107,2 +107,3 @@ /** | ||
const mode = context.options[0] || MODE_ALWAYS; | ||
const sourceCode = context.getSourceCode(); | ||
@@ -135,3 +136,2 @@ /** | ||
fix(fixer) { | ||
const sourceCode = context.getSourceCode(); | ||
const tokens = sourceCode.getTokens(node); | ||
@@ -167,4 +167,4 @@ const lastToken = tokens[tokens.length - 1]; // Parenthesis. | ||
return { | ||
"Program:exit"() { | ||
const scope = context.getScope(); | ||
"Program:exit"(node) { | ||
const scope = sourceCode.getScope(node); | ||
let variable; | ||
@@ -176,6 +176,6 @@ | ||
variable.references.forEach(reference => { | ||
const node = reference.identifier; | ||
const idNode = reference.identifier; | ||
if (astUtils.isCallee(node)) { | ||
checkArguments(node.parent); | ||
if (astUtils.isCallee(idNode)) { | ||
checkArguments(idNode.parent); | ||
} | ||
@@ -189,8 +189,8 @@ }); | ||
variable.references.forEach(reference => { | ||
const node = reference.identifier.parent; | ||
const maybeCallee = node.parent.type === "ChainExpression" | ||
? node.parent | ||
: node; | ||
const parentNode = reference.identifier.parent; | ||
const maybeCallee = parentNode.parent.type === "ChainExpression" | ||
? parentNode.parent | ||
: parentNode; | ||
if (isParseIntMethod(node) && astUtils.isCallee(maybeCallee)) { | ||
if (isParseIntMethod(parentNode) && astUtils.isCallee(maybeCallee)) { | ||
checkArguments(maybeCallee.parent); | ||
@@ -197,0 +197,0 @@ } |
@@ -207,4 +207,4 @@ /** | ||
return { | ||
onCodePathStart(codePath) { | ||
const scope = context.getScope(); | ||
onCodePathStart(codePath, node) { | ||
const scope = sourceCode.getScope(node); | ||
const shouldVerify = | ||
@@ -211,0 +211,0 @@ scope.type === "function" && |
@@ -17,3 +17,5 @@ /** | ||
getStringIfConstant | ||
} = require("eslint-utils"); | ||
} = require("@eslint-community/eslint-utils"); | ||
const astUtils = require("./utils/ast-utils.js"); | ||
const { isValidWithUnicodeFlag } = require("./utils/regular-expressions"); | ||
@@ -35,3 +37,6 @@ //------------------------------------------------------------------------------ | ||
hasSuggestions: true, | ||
messages: { | ||
addUFlag: "Add the 'u' flag.", | ||
requireUFlag: "Use the 'u' flag." | ||
@@ -44,2 +49,5 @@ }, | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
return { | ||
@@ -50,8 +58,21 @@ "Literal[regex]"(node) { | ||
if (!flags.includes("u")) { | ||
context.report({ node, messageId: "requireUFlag" }); | ||
context.report({ | ||
messageId: "requireUFlag", | ||
node, | ||
suggest: isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, node.regex.pattern) | ||
? [ | ||
{ | ||
fix(fixer) { | ||
return fixer.insertTextAfter(node, "u"); | ||
}, | ||
messageId: "addUFlag" | ||
} | ||
] | ||
: null | ||
}); | ||
} | ||
}, | ||
Program() { | ||
const scope = context.getScope(); | ||
Program(node) { | ||
const scope = sourceCode.getScope(node); | ||
const tracker = new ReferenceTracker(scope); | ||
@@ -62,8 +83,47 @@ const trackMap = { | ||
for (const { node } of tracker.iterateGlobalReferences(trackMap)) { | ||
const flagsNode = node.arguments[1]; | ||
for (const { node: refNode } of tracker.iterateGlobalReferences(trackMap)) { | ||
const [patternNode, flagsNode] = refNode.arguments; | ||
if (patternNode && patternNode.type === "SpreadElement") { | ||
continue; | ||
} | ||
const pattern = getStringIfConstant(patternNode, scope); | ||
const flags = getStringIfConstant(flagsNode, scope); | ||
if (!flagsNode || (typeof flags === "string" && !flags.includes("u"))) { | ||
context.report({ node, messageId: "requireUFlag" }); | ||
context.report({ | ||
messageId: "requireUFlag", | ||
node: refNode, | ||
suggest: typeof pattern === "string" && isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, pattern) | ||
? [ | ||
{ | ||
fix(fixer) { | ||
if (flagsNode) { | ||
if ((flagsNode.type === "Literal" && typeof flagsNode.value === "string") || flagsNode.type === "TemplateLiteral") { | ||
const flagsNodeText = sourceCode.getText(flagsNode); | ||
return fixer.replaceText(flagsNode, [ | ||
flagsNodeText.slice(0, flagsNodeText.length - 1), | ||
flagsNodeText.slice(flagsNodeText.length - 1) | ||
].join("u")); | ||
} | ||
// We intentionally don't suggest concatenating + "u" to non-literals | ||
return null; | ||
} | ||
const penultimateToken = sourceCode.getLastToken(refNode, { skip: 1 }); // skip closing parenthesis | ||
return fixer.insertTextAfter( | ||
penultimateToken, | ||
astUtils.isCommaToken(penultimateToken) | ||
? ' "u",' | ||
: ', "u"' | ||
); | ||
}, | ||
messageId: "addUFlag" | ||
} | ||
] | ||
: null | ||
}); | ||
} | ||
@@ -70,0 +130,0 @@ } |
@@ -38,2 +38,4 @@ /** | ||
const sourceCode = context.getSourceCode(); | ||
/** | ||
@@ -55,4 +57,4 @@ * Reports if node does not conform the rule in case rule is set to | ||
return { | ||
"Program:exit"() { | ||
const scope = context.getScope(); | ||
"Program:exit"(node) { | ||
const scope = sourceCode.getScope(node); | ||
const variable = astUtils.getVariableByName(scope, "Symbol"); | ||
@@ -62,6 +64,6 @@ | ||
variable.references.forEach(reference => { | ||
const node = reference.identifier; | ||
const idNode = reference.identifier; | ||
if (astUtils.isCallee(node)) { | ||
checkArgument(node.parent); | ||
if (astUtils.isCallee(idNode)) { | ||
checkArgument(idNode.parent); | ||
} | ||
@@ -68,0 +70,0 @@ }); |
@@ -47,3 +47,3 @@ /** | ||
OPERATORS = new Set(["==", "===", "!=", "!=="]); | ||
const sourceCode = context.getSourceCode(); | ||
const requireStringLiterals = context.options[0] && context.options[0].requireStringLiterals; | ||
@@ -81,4 +81,4 @@ | ||
Program() { | ||
globalScope = context.getScope(); | ||
Program(node) { | ||
globalScope = sourceCode.getScope(node); | ||
}, | ||
@@ -88,3 +88,3 @@ | ||
if (isTypeofExpression(node)) { | ||
const parent = context.getAncestors().pop(); | ||
const parent = sourceCode.getAncestors(node).pop(); | ||
@@ -91,0 +91,0 @@ if (parent.type === "BinaryExpression" && OPERATORS.has(parent.operator)) { |
@@ -13,3 +13,3 @@ /** | ||
const astUtils = require("./utils/ast-utils"); | ||
const eslintUtils = require("eslint-utils"); | ||
const eslintUtils = require("@eslint-community/eslint-utils"); | ||
@@ -16,0 +16,0 @@ //---------------------------------------------------------------------- |
@@ -43,3 +43,3 @@ /** | ||
const afterToken = sourceCode.getTokenAfter(node); | ||
const ancestors = context.getAncestors(); | ||
const ancestors = sourceCode.getAncestors(node); | ||
const grandparent = ancestors[ancestors.length - 1]; | ||
@@ -46,0 +46,0 @@ |
@@ -346,3 +346,3 @@ /** | ||
isComparisonOperator(node.operator) && | ||
!(exceptRange && isRangeTest(context.getAncestors().pop())) | ||
!(exceptRange && isRangeTest(sourceCode.getAncestors(node).pop())) | ||
) { | ||
@@ -349,0 +349,0 @@ context.report({ |
@@ -12,3 +12,3 @@ /** | ||
const | ||
{ isCommentToken } = require("eslint-utils"), | ||
{ isCommentToken } = require("@eslint-community/eslint-utils"), | ||
TokenStore = require("./token-store"), | ||
@@ -19,2 +19,8 @@ astUtils = require("../shared/ast-utils"), | ||
//------------------------------------------------------------------------------ | ||
// Type Definitions | ||
//------------------------------------------------------------------------------ | ||
/** @typedef {import("eslint-scope").Variable} Variable */ | ||
//------------------------------------------------------------------------------ | ||
// Private | ||
@@ -148,2 +154,4 @@ //------------------------------------------------------------------------------ | ||
const caches = Symbol("caches"); | ||
/** | ||
@@ -182,2 +190,9 @@ * Represents parsed source code. | ||
/** | ||
* General purpose caching for the class. | ||
*/ | ||
this[caches] = new Map([ | ||
["scopes", new WeakMap()] | ||
]); | ||
/** | ||
* The flag to indicate that the source code has Unicode BOM. | ||
@@ -595,4 +610,82 @@ * @type {boolean} | ||
} | ||
/** | ||
* Gets the scope for the given node | ||
* @param {ASTNode} currentNode The node to get the scope of | ||
* @returns {eslint-scope.Scope} The scope information for this node | ||
* @throws {TypeError} If the `currentNode` argument is missing. | ||
*/ | ||
getScope(currentNode) { | ||
if (!currentNode) { | ||
throw new TypeError("Missing required argument: node."); | ||
} | ||
// check cache first | ||
const cache = this[caches].get("scopes"); | ||
const cachedScope = cache.get(currentNode); | ||
if (cachedScope) { | ||
return cachedScope; | ||
} | ||
// On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope. | ||
const inner = currentNode.type !== "Program"; | ||
for (let node = currentNode; node; node = node.parent) { | ||
const scope = this.scopeManager.acquire(node, inner); | ||
if (scope) { | ||
if (scope.type === "function-expression-name") { | ||
cache.set(currentNode, scope.childScopes[0]); | ||
return scope.childScopes[0]; | ||
} | ||
cache.set(currentNode, scope); | ||
return scope; | ||
} | ||
} | ||
cache.set(currentNode, this.scopeManager.scopes[0]); | ||
return this.scopeManager.scopes[0]; | ||
} | ||
/** | ||
* Gets all of the declared variables in the scope associated | ||
* with `node`. This is a convenience method that passes through | ||
* to the same method on the `scopeManager`. | ||
* @param {ASTNode} node The node from which to retrieve the scope to check. | ||
* @returns {Array<Variable>} An array of variable nodes representing | ||
* the declared variables in the scope associated with `node`. | ||
*/ | ||
getDeclaredVariables(node) { | ||
return this.scopeManager.getDeclaredVariables(node); | ||
} | ||
/* eslint-disable class-methods-use-this -- node is owned by SourceCode */ | ||
/** | ||
* Gets all the ancestors of a given node | ||
* @param {ASTNode} node The node | ||
* @returns {Array<ASTNode>} All the ancestor nodes in the AST, not including the provided node, starting | ||
* from the root node at index 0 and going inwards to the parent node. | ||
* @throws {TypeError} When `node` is missing. | ||
*/ | ||
getAncestors(node) { | ||
if (!node) { | ||
throw new TypeError("Missing required argument: node."); | ||
} | ||
const ancestorsStartingAtParent = []; | ||
for (let ancestor = node.parent; ancestor; ancestor = ancestor.parent) { | ||
ancestorsStartingAtParent.push(ancestor); | ||
} | ||
return ancestorsStartingAtParent.reverse(); | ||
} | ||
/* eslint-enable class-methods-use-this -- node is owned by SourceCode */ | ||
} | ||
module.exports = SourceCode; |
@@ -12,3 +12,3 @@ /** | ||
const assert = require("assert"); | ||
const { isCommentToken } = require("eslint-utils"); | ||
const { isCommentToken } = require("@eslint-community/eslint-utils"); | ||
const cursors = require("./cursors"); | ||
@@ -15,0 +15,0 @@ const ForwardTokenCursor = require("./forward-token-cursor"); |
@@ -52,4 +52,9 @@ /** | ||
const index = indexMap[startLoc - 1]; | ||
const token = (index >= 0 && index < tokens.length) ? tokens[index] : null; | ||
const token = tokens[index]; | ||
// If the mapped index is out of bounds, the returned cursor index will point after the end of the tokens array. | ||
if (!token) { | ||
return tokens.length; | ||
} | ||
/* | ||
@@ -59,3 +64,3 @@ * For the map of "comment's location -> token's index", it points the next token of a comment. | ||
*/ | ||
if (token && token.range[0] >= startLoc) { | ||
if (token.range[0] >= startLoc) { | ||
return index; | ||
@@ -82,4 +87,9 @@ } | ||
const index = indexMap[endLoc - 1]; | ||
const token = (index >= 0 && index < tokens.length) ? tokens[index] : null; | ||
const token = tokens[index]; | ||
// If the mapped index is out of bounds, the returned cursor index will point before the end of the tokens array. | ||
if (!token) { | ||
return tokens.length - 1; | ||
} | ||
/* | ||
@@ -89,3 +99,3 @@ * For the map of "comment's location -> token's index", it points the next token of a comment. | ||
*/ | ||
if (token && token.range[1] > endLoc) { | ||
if (token.range[1] > endLoc) { | ||
return index - 1; | ||
@@ -92,0 +102,0 @@ } |
@@ -13,4 +13,4 @@ "use strict"; | ||
If you think you already have a configuration file or if you need more help, please stop by the ESLint chat room: https://eslint.org/chat/help | ||
If you think you already have a configuration file or if you need more help, please stop by the ESLint Discord server: https://eslint.org/chat | ||
`.trimStart(); | ||
}; |
{ | ||
"name": "eslint", | ||
"version": "8.33.0", | ||
"version": "8.38.0", | ||
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>", | ||
@@ -40,2 +40,6 @@ "description": "An AST-based pattern checker for JavaScript.", | ||
"*.md": "markdownlint --fix", | ||
"lib/rules/*.js": [ | ||
"node tools/update-eslint-all.js", | ||
"git add packages/js/src/configs/eslint-all.js" | ||
], | ||
"docs/src/rules/*.md": [ | ||
@@ -60,3 +64,6 @@ "node tools/fetch-docs-links.js", | ||
"dependencies": { | ||
"@eslint/eslintrc": "^1.4.1", | ||
"@eslint-community/eslint-utils": "^4.2.0", | ||
"@eslint-community/regexpp": "^4.4.0", | ||
"@eslint/eslintrc": "^2.0.2", | ||
"@eslint/js": "8.38.0", | ||
"@humanwhocodes/config-array": "^0.11.8", | ||
@@ -72,6 +79,5 @@ "@humanwhocodes/module-importer": "^1.0.1", | ||
"eslint-scope": "^7.1.1", | ||
"eslint-utils": "^3.0.0", | ||
"eslint-visitor-keys": "^3.3.0", | ||
"espree": "^9.4.0", | ||
"esquery": "^1.4.0", | ||
"eslint-visitor-keys": "^3.4.0", | ||
"espree": "^9.5.1", | ||
"esquery": "^1.4.2", | ||
"esutils": "^2.0.2", | ||
@@ -97,3 +103,2 @@ "fast-deep-equal": "^3.1.3", | ||
"optionator": "^0.9.1", | ||
"regexpp": "^3.2.0", | ||
"strip-ansi": "^6.0.1", | ||
@@ -100,0 +105,0 @@ "strip-json-comments": "^3.1.0", |
@@ -19,4 +19,3 @@ [![npm version](https://img.shields.io/npm/v/eslint.svg)](https://www.npmjs.com/package/eslint) | ||
[Twitter](https://twitter.com/geteslint) | | ||
[Mailing List](https://groups.google.com/group/eslint) | | ||
[Chat Room](https://eslint.org/chat) | ||
[Discord](https://eslint.org/chat) | ||
@@ -133,3 +132,3 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code. In many ways, it is similar to JSLint and JSHint with a few exceptions: | ||
Join our [Mailing List](https://groups.google.com/group/eslint) or [Chatroom](https://eslint.org/chat). | ||
Open a [discussion](https://github.com/eslint/eslint/discussions) or stop by our [Discord server](https://eslint.org/chat). | ||
@@ -218,7 +217,2 @@ ### Why doesn't ESLint lock dependency versions? | ||
</td><td align="center" valign="top" width="11%"> | ||
<a href="https://github.com/btmills"> | ||
<img src="https://github.com/btmills.png?s=75" width="75" height="75"><br /> | ||
Brandon Mills | ||
</a> | ||
</td><td align="center" valign="top" width="11%"> | ||
<a href="https://github.com/mdjermanovic"> | ||
@@ -256,5 +250,5 @@ <img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75"><br /> | ||
</td><td align="center" valign="top" width="11%"> | ||
<a href="https://github.com/SaraSoueidan"> | ||
<img src="https://github.com/SaraSoueidan.png?s=75" width="75" height="75"><br /> | ||
Sara Soueidan | ||
<a href="https://github.com/fasttime"> | ||
<img src="https://github.com/fasttime.png?s=75" width="75" height="75"><br /> | ||
Francesco Trotta | ||
</a> | ||
@@ -300,4 +294,4 @@ </td><td align="center" valign="top" width="11%"> | ||
<p><a href="https://ridicorp.com/career/"><img src="https://images.opencollective.com/ridi-corporation/175dcf3/logo.png" alt="RIDI" height="96"></a> <a href="https://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a></p><h3>Silver Sponsors</h3> | ||
<p><a href="https://sentry.io"><img src="https://avatars.githubusercontent.com/u/1396951?v=4" alt="Sentry" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3> | ||
<p><a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://quickbookstoolhub.com"><img src="https://avatars.githubusercontent.com/u/95090305?u=e5bc398ef775c9ed19f955c675cdc1fb6abf01df&v=4" alt="QuickBooks Tool hub" height="32"></a></p> | ||
<p><a href="https://sentry.io"><img src="https://avatars.githubusercontent.com/u/1396951?v=4" alt="Sentry" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a></p><h3>Bronze Sponsors</h3> | ||
<p><a href="https://paydaysay.com/"><img src="https://images.opencollective.com/payday-say-organization/9cd2467/logo.png" alt="PayDay Say" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://quickbookstoolhub.com"><img src="https://avatars.githubusercontent.com/u/95090305?u=e5bc398ef775c9ed19f955c675cdc1fb6abf01df&v=4" alt="QuickBooks Tool hub" height="32"></a></p> | ||
<!--sponsorsend--> | ||
@@ -304,0 +298,0 @@ |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2877449
68117
40
401
299
+ Added@eslint/js@8.38.0
+ Added@eslint-community/eslint-utils@4.4.0(transitive)
+ Added@eslint-community/regexpp@4.11.1(transitive)
+ Added@eslint/eslintrc@2.1.4(transitive)
+ Added@eslint/js@8.38.0(transitive)
- Removedeslint-utils@^3.0.0
- Removedregexpp@^3.2.0
- Removed@eslint/eslintrc@1.4.1(transitive)
- Removedeslint-utils@3.0.0(transitive)
- Removedeslint-visitor-keys@2.1.0(transitive)
- Removedregexpp@3.2.0(transitive)
Updated@eslint/eslintrc@^2.0.2
Updatedeslint-visitor-keys@^3.4.0
Updatedespree@^9.5.1
Updatedesquery@^1.4.2