Update checked-in dependencies

This commit is contained in:
github-actions[bot] 2023-07-13 09:09:17 +00:00
parent 4fad06f438
commit 40a500c743
4168 changed files with 298222 additions and 374905 deletions

View file

@ -142,7 +142,7 @@ module.exports = {
docs: {
description: "Enforce getter and setter pairs in objects and classes",
recommended: false,
url: "https://eslint.org/docs/rules/accessor-pairs"
url: "https://eslint.org/docs/latest/rules/accessor-pairs"
},
schema: [{
@ -178,7 +178,7 @@ module.exports = {
const checkGetWithoutSet = config.getWithoutSet === true;
const checkSetWithoutGet = config.setWithoutGet !== false;
const enforceForClassMembers = config.enforceForClassMembers !== false;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Reports the given node.
@ -223,43 +223,6 @@ module.exports = {
}
}
/**
* Creates a new `AccessorData` object for the given getter or setter node.
* @param {ASTNode} node A getter or setter node.
* @returns {AccessorData} New `AccessorData` object that contains the given node.
* @private
*/
function createAccessorData(node) {
const name = astUtils.getStaticPropertyName(node);
const key = (name !== null) ? name : sourceCode.getTokens(node.key);
return {
key,
getters: node.kind === "get" ? [node] : [],
setters: node.kind === "set" ? [node] : []
};
}
/**
* Merges the given `AccessorData` object into the given accessors list.
* @param {AccessorData[]} accessors The list to merge into.
* @param {AccessorData} accessorData The object to merge.
* @returns {AccessorData[]} The same instance with the merged object.
* @private
*/
function mergeAccessorData(accessors, accessorData) {
const equalKeyElement = accessors.find(a => areEqualKeys(a.key, accessorData.key));
if (equalKeyElement) {
equalKeyElement.getters.push(...accessorData.getters);
equalKeyElement.setters.push(...accessorData.setters);
} else {
accessors.push(accessorData);
}
return accessors;
}
/**
* Checks accessor pairs in the given list of nodes.
* @param {ASTNode[]} nodes The list to check.
@ -267,10 +230,39 @@ module.exports = {
* @private
*/
function checkList(nodes) {
const accessors = nodes
.filter(isAccessorKind)
.map(createAccessorData)
.reduce(mergeAccessorData, []);
const accessors = [];
let found = false;
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (isAccessorKind(node)) {
// Creates a new `AccessorData` object for the given getter or setter node.
const name = astUtils.getStaticPropertyName(node);
const key = (name !== null) ? name : sourceCode.getTokens(node.key);
// Merges the given `AccessorData` object into the given accessors list.
for (let j = 0; j < accessors.length; j++) {
const accessor = accessors[j];
if (areEqualKeys(accessor.key, key)) {
accessor.getters.push(...node.kind === "get" ? [node] : []);
accessor.setters.push(...node.kind === "set" ? [node] : []);
found = true;
break;
}
}
if (!found) {
accessors.push({
key,
getters: node.kind === "get" ? [node] : [],
setters: node.kind === "set" ? [node] : []
});
}
found = false;
}
}
for (const { getters, setters } of accessors) {
if (checkSetWithoutGet && setters.length && !getters.length) {

View file

@ -19,7 +19,7 @@ module.exports = {
docs: {
description: "Enforce linebreaks after opening and before closing array brackets",
recommended: false,
url: "https://eslint.org/docs/rules/array-bracket-newline"
url: "https://eslint.org/docs/latest/rules/array-bracket-newline"
},
fixable: "whitespace",
@ -56,7 +56,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
//----------------------------------------------------------------------

View file

@ -18,7 +18,7 @@ module.exports = {
docs: {
description: "Enforce consistent spacing inside array brackets",
recommended: false,
url: "https://eslint.org/docs/rules/array-bracket-spacing"
url: "https://eslint.org/docs/latest/rules/array-bracket-spacing"
},
fixable: "whitespace",
@ -53,7 +53,7 @@ module.exports = {
},
create(context) {
const spaced = context.options[0] === "always",
sourceCode = context.getSourceCode();
sourceCode = context.sourceCode;
/**
* Determines whether an option is set, relative to the spacing option.

View file

@ -16,7 +16,7 @@ const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
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;
/**
* Checks a given code path segment is reachable.
@ -141,7 +141,7 @@ module.exports = {
docs: {
description: "Enforce `return` statements in callbacks of array methods",
recommended: false,
url: "https://eslint.org/docs/rules/array-callback-return"
url: "https://eslint.org/docs/latest/rules/array-callback-return"
},
schema: [
@ -172,7 +172,7 @@ module.exports = {
create(context) {
const options = context.options[0] || { allowImplicit: false, checkForEach: false };
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
let funcInfo = {
arrayMethodName: null,

View file

@ -19,7 +19,7 @@ module.exports = {
docs: {
description: "Enforce line breaks after each array element",
recommended: false,
url: "https://eslint.org/docs/rules/array-element-newline"
url: "https://eslint.org/docs/latest/rules/array-element-newline"
},
fixable: "whitespace",
@ -47,6 +47,7 @@ module.exports = {
]
}
},
type: "array",
items: [
{
oneOf: [
@ -78,7 +79,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
//----------------------------------------------------------------------
// Helpers
@ -239,19 +240,25 @@ module.exports = {
.some(element => element.loc.start.line !== element.loc.end.line);
}
const linebreaksCount = node.elements.map((element, i) => {
let linebreaksCount = 0;
for (let i = 0; i < node.elements.length; i++) {
const element = node.elements[i];
const previousElement = elements[i - 1];
if (i === 0 || element === null || previousElement === null) {
return false;
continue;
}
const commaToken = sourceCode.getFirstTokenBetween(previousElement, element, astUtils.isCommaToken);
const lastTokenOfPreviousElement = sourceCode.getTokenBefore(commaToken);
const firstTokenOfCurrentElement = sourceCode.getTokenAfter(commaToken);
return !astUtils.isTokenOnSameLine(lastTokenOfPreviousElement, firstTokenOfCurrentElement);
}).filter(isBreak => isBreak === true).length;
if (!astUtils.isTokenOnSameLine(lastTokenOfPreviousElement, firstTokenOfCurrentElement)) {
linebreaksCount++;
}
}
const needsLinebreaks = (
elements.length >= options.minItems ||

View file

@ -22,7 +22,7 @@ module.exports = {
docs: {
description: "Require braces around arrow function bodies",
recommended: false,
url: "https://eslint.org/docs/rules/arrow-body-style"
url: "https://eslint.org/docs/latest/rules/arrow-body-style"
},
schema: {
@ -74,7 +74,7 @@ module.exports = {
const asNeeded = !options[0] || options[0] === "as-needed";
const never = options[0] === "never";
const requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
let funcInfo = null;
/**

View file

@ -35,7 +35,7 @@ module.exports = {
docs: {
description: "Require parentheses around arrow function arguments",
recommended: false,
url: "https://eslint.org/docs/rules/arrow-parens"
url: "https://eslint.org/docs/latest/rules/arrow-parens"
},
fixable: "code",
@ -69,7 +69,7 @@ module.exports = {
const asNeeded = context.options[0] === "as-needed";
const requireForBlockBody = asNeeded && context.options[1] && context.options[1].requireForBlockBody === true;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Finds opening paren of parameters for the given arrow function, if it exists.

View file

@ -22,7 +22,7 @@ module.exports = {
docs: {
description: "Enforce consistent spacing before and after the arrow in arrow functions",
recommended: false,
url: "https://eslint.org/docs/rules/arrow-spacing"
url: "https://eslint.org/docs/latest/rules/arrow-spacing"
},
fixable: "whitespace",
@ -61,7 +61,7 @@ module.exports = {
rule.before = rule.before !== false;
rule.after = rule.after !== false;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Get tokens of arrow(`=>`) and before/after arrow.

View file

@ -16,18 +16,19 @@ module.exports = {
docs: {
description: "Enforce the use of variables within the scope they are defined",
recommended: false,
url: "https://eslint.org/docs/rules/block-scoped-var"
url: "https://eslint.org/docs/latest/rules/block-scoped-var"
},
schema: [],
messages: {
outOfScope: "'{{name}}' used outside of binding context."
outOfScope: "'{{name}}' declared on line {{definitionLine}} column {{definitionColumn}} is used outside of binding context."
}
},
create(context) {
let stack = [];
const sourceCode = context.sourceCode;
/**
* Makes a block scope.
@ -49,12 +50,22 @@ module.exports = {
/**
* Reports a given reference.
* @param {eslint-scope.Reference} reference A reference to report.
* @param {eslint-scope.Definition} definition A definition for which to report reference.
* @returns {void}
*/
function report(reference) {
function report(reference, definition) {
const identifier = reference.identifier;
const definitionPosition = definition.name.loc.start;
context.report({ node: identifier, messageId: "outOfScope", data: { name: identifier.name } });
context.report({
node: identifier,
messageId: "outOfScope",
data: {
name: identifier.name,
definitionLine: definitionPosition.line,
definitionColumn: definitionPosition.column + 1
}
});
}
/**
@ -83,7 +94,7 @@ module.exports = {
}
// Gets declared variables, and checks its references.
const variables = context.getDeclaredVariables(node);
const variables = sourceCode.getDeclaredVariables(node);
for (let i = 0; i < variables.length; ++i) {
@ -91,7 +102,7 @@ module.exports = {
variables[i]
.references
.filter(isOutsideOfScope)
.forEach(report);
.forEach(ref => report(ref, variables[i].defs.find(def => def.parent === node)));
}
}

View file

@ -19,7 +19,7 @@ module.exports = {
docs: {
description: "Disallow or enforce spaces inside of blocks after opening block and before closing block",
recommended: false,
url: "https://eslint.org/docs/rules/block-spacing"
url: "https://eslint.org/docs/latest/rules/block-spacing"
},
fixable: "whitespace",
@ -37,7 +37,7 @@ module.exports = {
create(context) {
const always = (context.options[0] !== "never"),
messageId = always ? "missing" : "extra",
sourceCode = context.getSourceCode();
sourceCode = context.sourceCode;
/**
* Gets the open brace token from a given node.

View file

@ -19,7 +19,7 @@ module.exports = {
docs: {
description: "Enforce consistent brace style for blocks",
recommended: false,
url: "https://eslint.org/docs/rules/brace-style"
url: "https://eslint.org/docs/latest/rules/brace-style"
},
schema: [
@ -53,7 +53,7 @@ module.exports = {
create(context) {
const style = context.options[0] || "1tbs",
params = context.options[1] || {},
sourceCode = context.getSourceCode();
sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers

View file

@ -21,7 +21,7 @@ module.exports = {
docs: {
description: "Require `return` statements after callbacks",
recommended: false,
url: "https://eslint.org/docs/rules/callback-return"
url: "https://eslint.org/docs/latest/rules/callback-return"
},
schema: [{
@ -37,7 +37,7 @@ module.exports = {
create(context) {
const callbacks = context.options[0] || ["callback", "cb", "next"],
sourceCode = context.getSourceCode();
sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers

View file

@ -23,7 +23,7 @@ module.exports = {
docs: {
description: "Enforce camelcase naming convention",
recommended: false,
url: "https://eslint.org/docs/rules/camelcase"
url: "https://eslint.org/docs/latest/rules/camelcase"
},
schema: [
@ -73,6 +73,7 @@ module.exports = {
const ignoreImports = options.ignoreImports;
const ignoreGlobals = options.ignoreGlobals;
const allow = options.allow || [];
const sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers
@ -245,8 +246,8 @@ module.exports = {
return {
// Report camelcase of global variable references ------------------
Program() {
const scope = context.getScope();
Program(node) {
const scope = sourceCode.getScope(node);
if (!ignoreGlobals) {
@ -295,7 +296,7 @@ module.exports = {
"ClassExpression",
"CatchClause"
]](node) {
for (const variable of context.getDeclaredVariables(node)) {
for (const variable of sourceCode.getDeclaredVariables(node)) {
if (isGoodName(variable.name)) {
continue;
}
@ -345,7 +346,7 @@ module.exports = {
// Report camelcase in import --------------------------------------
ImportDeclaration(node) {
for (const variable of context.getDeclaredVariables(node)) {
for (const variable of sourceCode.getDeclaredVariables(node)) {
if (isGoodName(variable.name)) {
continue;
}

View file

@ -107,7 +107,7 @@ module.exports = {
docs: {
description: "Enforce or disallow capitalization of the first letter of a comment",
recommended: false,
url: "https://eslint.org/docs/rules/capitalized-comments"
url: "https://eslint.org/docs/latest/rules/capitalized-comments"
},
fixable: "code",
@ -139,7 +139,7 @@ module.exports = {
const capitalize = context.options[0] || "always",
normalizedOptions = getAllNormalizedOptions(context.options[1]),
sourceCode = context.getSourceCode();
sourceCode = context.sourceCode;
createRegExpForIgnorePatterns(normalizedOptions);

View file

@ -23,7 +23,7 @@ module.exports = {
docs: {
description: "Enforce that class methods utilize `this`",
recommended: false,
url: "https://eslint.org/docs/rules/class-methods-use-this"
url: "https://eslint.org/docs/latest/rules/class-methods-use-this"
},
schema: [{
@ -133,7 +133,7 @@ module.exports = {
if (isIncludedInstanceMethod(node.parent) && !methodUsesThis) {
context.report({
node,
loc: astUtils.getFunctionHeadLoc(node, context.getSourceCode()),
loc: astUtils.getFunctionHeadLoc(node, context.sourceCode),
messageId: "missingThis",
data: {
name: astUtils.getFunctionNameWithKind(node)

View file

@ -78,7 +78,7 @@ module.exports = {
docs: {
description: "Require or disallow trailing commas",
recommended: false,
url: "https://eslint.org/docs/rules/comma-dangle"
url: "https://eslint.org/docs/latest/rules/comma-dangle"
},
fixable: "code",
@ -136,7 +136,7 @@ module.exports = {
create(context) {
const options = normalizeOptions(context.options[0], context.languageOptions.ecmaVersion);
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Gets the last item of the given node.

View file

@ -18,7 +18,7 @@ module.exports = {
docs: {
description: "Enforce consistent spacing before and after commas",
recommended: false,
url: "https://eslint.org/docs/rules/comma-spacing"
url: "https://eslint.org/docs/latest/rules/comma-spacing"
},
fixable: "whitespace",
@ -48,7 +48,7 @@ module.exports = {
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const tokensAndComments = sourceCode.tokensAndComments;
const options = {

View file

@ -19,7 +19,7 @@ module.exports = {
docs: {
description: "Enforce consistent comma style",
recommended: false,
url: "https://eslint.org/docs/rules/comma-style"
url: "https://eslint.org/docs/latest/rules/comma-style"
},
fixable: "code",
@ -51,7 +51,7 @@ module.exports = {
create(context) {
const style = context.options[0] || "last",
sourceCode = context.getSourceCode();
sourceCode = context.sourceCode;
const exceptions = {
ArrayPattern: true,
ArrowFunctionExpression: true,

View file

@ -25,7 +25,7 @@ module.exports = {
docs: {
description: "Enforce a maximum cyclomatic complexity allowed in a program",
recommended: false,
url: "https://eslint.org/docs/rules/complexity"
url: "https://eslint.org/docs/latest/rules/complexity"
},
schema: [

View file

@ -18,7 +18,7 @@ module.exports = {
docs: {
description: "Enforce consistent spacing inside computed property brackets",
recommended: false,
url: "https://eslint.org/docs/rules/computed-property-spacing"
url: "https://eslint.org/docs/latest/rules/computed-property-spacing"
},
fixable: "whitespace",
@ -49,7 +49,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never"
const enforceForClassMembers = !context.options[1] || context.options[1].enforceForClassMembers;

View file

@ -48,7 +48,7 @@ module.exports = {
docs: {
description: "Require `return` statements to either always or never specify values",
recommended: false,
url: "https://eslint.org/docs/rules/consistent-return"
url: "https://eslint.org/docs/latest/rules/consistent-return"
},
schema: [{
@ -104,7 +104,7 @@ module.exports = {
} else if (node.type === "ArrowFunctionExpression") {
// `=>` token
loc = context.getSourceCode().getTokenBefore(node.body, astUtils.isArrowToken).loc;
loc = context.sourceCode.getTokenBefore(node.body, astUtils.isArrowToken).loc;
} else if (
node.parent.type === "MethodDefinition" ||
(node.parent.type === "Property" && node.parent.method)
@ -115,7 +115,7 @@ module.exports = {
} else {
// Function name or `function` keyword.
loc = (node.id || context.getSourceCode().getFirstToken(node)).loc;
loc = (node.id || context.sourceCode.getFirstToken(node)).loc;
}
if (!name) {

View file

@ -16,7 +16,7 @@ module.exports = {
docs: {
description: "Enforce consistent naming when capturing the current execution context",
recommended: false,
url: "https://eslint.org/docs/rules/consistent-this"
url: "https://eslint.org/docs/latest/rules/consistent-this"
},
schema: {
@ -36,6 +36,7 @@ module.exports = {
create(context) {
let aliases = [];
const sourceCode = context.sourceCode;
if (context.options.length === 0) {
aliases.push("that");
@ -115,10 +116,11 @@ module.exports = {
/**
* 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);
aliases.forEach(alias => {
checkWasAssigned(alias, scope);

View file

@ -124,7 +124,7 @@ module.exports = {
docs: {
description: "Require `super()` calls in constructors",
recommended: true,
url: "https://eslint.org/docs/rules/constructor-super"
url: "https://eslint.org/docs/latest/rules/constructor-super"
},
schema: [],

View file

@ -22,7 +22,7 @@ module.exports = {
docs: {
description: "Enforce consistent brace style for all control statements",
recommended: false,
url: "https://eslint.org/docs/rules/curly"
url: "https://eslint.org/docs/latest/rules/curly"
},
schema: {
@ -70,7 +70,7 @@ module.exports = {
const multiOrNest = (context.options[0] === "multi-or-nest");
const consistent = (context.options[1] === "consistent");
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Enforce default clauses in switch statements to be last",
recommended: false,
url: "https://eslint.org/docs/rules/default-case-last"
url: "https://eslint.org/docs/latest/rules/default-case-last"
},
schema: [],

View file

@ -18,7 +18,7 @@ module.exports = {
docs: {
description: "Require `default` cases in `switch` statements",
recommended: false,
url: "https://eslint.org/docs/rules/default-case"
url: "https://eslint.org/docs/latest/rules/default-case"
},
schema: [{
@ -42,7 +42,7 @@ module.exports = {
? new RegExp(options.commentPattern, "u")
: DEFAULT_COMMENT_PATTERN;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers

View file

@ -13,7 +13,7 @@ module.exports = {
docs: {
description: "Enforce default parameters to be last",
recommended: false,
url: "https://eslint.org/docs/rules/default-param-last"
url: "https://eslint.org/docs/latest/rules/default-param-last"
},
schema: [],

View file

@ -19,7 +19,7 @@ module.exports = {
docs: {
description: "Enforce consistent newlines before and after dots",
recommended: false,
url: "https://eslint.org/docs/rules/dot-location"
url: "https://eslint.org/docs/latest/rules/dot-location"
},
schema: [
@ -43,7 +43,7 @@ module.exports = {
// default to onObject if no preference is passed
const onObject = config === "object" || !config;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Reports if the dot between object and property is on the correct location.

View file

@ -28,7 +28,7 @@ module.exports = {
docs: {
description: "Enforce dot notation whenever possible",
recommended: false,
url: "https://eslint.org/docs/rules/dot-notation"
url: "https://eslint.org/docs/latest/rules/dot-notation"
},
schema: [
@ -59,7 +59,7 @@ module.exports = {
create(context) {
const options = context.options[0] || {};
const allowKeywords = options.allowKeywords === void 0 || options.allowKeywords;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
let allowPattern;
@ -133,8 +133,7 @@ module.exports = {
}
if (
node.computed &&
node.property.type === "TemplateLiteral" &&
node.property.expressions.length === 0
astUtils.isStaticTemplateLiteral(node.property)
) {
checkComputedProperty(node, node.property.quasis[0].value.cooked);
}

View file

@ -16,7 +16,7 @@ module.exports = {
docs: {
description: "Require or disallow newline at the end of files",
recommended: false,
url: "https://eslint.org/docs/rules/eol-last"
url: "https://eslint.org/docs/latest/rules/eol-last"
},
fixable: "whitespace",
@ -40,7 +40,7 @@ module.exports = {
return {
Program: function checkBadEOF(node) {
const sourceCode = context.getSourceCode(),
const sourceCode = context.sourceCode,
src = sourceCode.getText(),
lastLine = sourceCode.lines[sourceCode.lines.length - 1],
location = {

View file

@ -23,7 +23,7 @@ module.exports = {
docs: {
description: "Require the use of `===` and `!==`",
recommended: false,
url: "https://eslint.org/docs/rules/eqeqeq"
url: "https://eslint.org/docs/latest/rules/eqeqeq"
},
schema: {
@ -68,7 +68,7 @@ module.exports = {
create(context) {
const config = context.options[0] || "always";
const options = context.options[1] || {};
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const nullOption = (config === "always")
? options.null || "always"

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Enforce \"for\" loop update clause moving the counter in the right direction",
recommended: true,
url: "https://eslint.org/docs/rules/for-direction"
url: "https://eslint.org/docs/latest/rules/for-direction"
},
fixable: null,

View file

@ -23,7 +23,7 @@ module.exports = {
docs: {
description: "Require or disallow spacing between function identifiers and their invocations",
recommended: false,
url: "https://eslint.org/docs/rules/func-call-spacing"
url: "https://eslint.org/docs/latest/rules/func-call-spacing"
},
fixable: "whitespace",
@ -73,7 +73,7 @@ module.exports = {
const never = context.options[0] !== "always";
const allowNewlines = !never && context.options[1] && context.options[1].allowNewlines;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const text = sourceCode.getText();
/**

View file

@ -76,7 +76,7 @@ module.exports = {
docs: {
description: "Require function names to match the name of the variable or property to which they are assigned",
recommended: false,
url: "https://eslint.org/docs/rules/func-name-matching"
url: "https://eslint.org/docs/latest/rules/func-name-matching"
},
schema: {

View file

@ -32,7 +32,7 @@ module.exports = {
docs: {
description: "Require or disallow named `function` expressions",
recommended: false,
url: "https://eslint.org/docs/rules/func-names"
url: "https://eslint.org/docs/latest/rules/func-names"
},
schema: {
@ -69,7 +69,7 @@ module.exports = {
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Returns the config option for the given node.
@ -159,7 +159,7 @@ module.exports = {
function handleFunction(node) {
// Skip recursive functions.
const nameVar = context.getDeclaredVariables(node)[0];
const nameVar = sourceCode.getDeclaredVariables(node)[0];
if (isFunctionName(nameVar) && nameVar.references.length > 0) {
return;

View file

@ -16,7 +16,7 @@ module.exports = {
docs: {
description: "Enforce the consistent use of either `function` declarations or expressions",
recommended: false,
url: "https://eslint.org/docs/rules/func-style"
url: "https://eslint.org/docs/latest/rules/func-style"
},
schema: [

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Enforce line breaks between arguments of a function call",
recommended: false,
url: "https://eslint.org/docs/rules/function-call-argument-newline"
url: "https://eslint.org/docs/latest/rules/function-call-argument-newline"
},
fixable: "whitespace",
@ -35,7 +35,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const checkers = {
unexpected: {

View file

@ -22,7 +22,7 @@ module.exports = {
docs: {
description: "Enforce consistent line breaks inside function parentheses",
recommended: false,
url: "https://eslint.org/docs/rules/function-paren-newline"
url: "https://eslint.org/docs/latest/rules/function-paren-newline"
},
fixable: "whitespace",
@ -57,7 +57,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const rawOption = context.options[0] || "multiline";
const multilineOption = rawOption === "multiline";
const multilineArgumentsOption = rawOption === "multiline-arguments";

View file

@ -33,7 +33,7 @@ module.exports = {
docs: {
description: "Enforce consistent spacing around `*` operators in generator functions",
recommended: false,
url: "https://eslint.org/docs/rules/generator-star-spacing"
url: "https://eslint.org/docs/latest/rules/generator-star-spacing"
},
fixable: "whitespace",
@ -102,7 +102,7 @@ module.exports = {
};
}(context.options[0] || {}));
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Checks if the given token is a star token or not.

View file

@ -37,7 +37,7 @@ module.exports = {
docs: {
description: "Enforce `return` statements in getters",
recommended: true,
url: "https://eslint.org/docs/rules/getter-return"
url: "https://eslint.org/docs/latest/rules/getter-return"
},
fixable: null,
@ -64,7 +64,7 @@ module.exports = {
create(context) {
const options = context.options[0] || { allowImplicit: false };
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
let funcInfo = {
upper: null,

View file

@ -61,7 +61,7 @@ module.exports = {
docs: {
description: "Require `require()` calls to be placed at top-level module scope",
recommended: false,
url: "https://eslint.org/docs/rules/global-require"
url: "https://eslint.org/docs/latest/rules/global-require"
},
schema: [],
@ -71,12 +71,14 @@ module.exports = {
},
create(context) {
const sourceCode = context.sourceCode;
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));
if (!isGoodRequire) {
context.report({ node, messageId: "unexpected" });

View file

@ -98,7 +98,7 @@ module.exports = {
docs: {
description: "Require grouped accessor pairs in object literals and classes",
recommended: false,
url: "https://eslint.org/docs/rules/grouped-accessor-pairs"
url: "https://eslint.org/docs/latest/rules/grouped-accessor-pairs"
},
schema: [
@ -115,7 +115,7 @@ module.exports = {
create(context) {
const order = context.options[0] || "anyOrder";
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Reports the given accessor pair.
@ -137,43 +137,6 @@ module.exports = {
});
}
/**
* Creates a new `AccessorData` object for the given getter or setter node.
* @param {ASTNode} node A getter or setter node.
* @returns {AccessorData} New `AccessorData` object that contains the given node.
* @private
*/
function createAccessorData(node) {
const name = astUtils.getStaticPropertyName(node);
const key = (name !== null) ? name : sourceCode.getTokens(node.key);
return {
key,
getters: node.kind === "get" ? [node] : [],
setters: node.kind === "set" ? [node] : []
};
}
/**
* Merges the given `AccessorData` object into the given accessors list.
* @param {AccessorData[]} accessors The list to merge into.
* @param {AccessorData} accessorData The object to merge.
* @returns {AccessorData[]} The same instance with the merged object.
* @private
*/
function mergeAccessorData(accessors, accessorData) {
const equalKeyElement = accessors.find(a => areEqualKeys(a.key, accessorData.key));
if (equalKeyElement) {
equalKeyElement.getters.push(...accessorData.getters);
equalKeyElement.setters.push(...accessorData.setters);
} else {
accessors.push(accessorData);
}
return accessors;
}
/**
* Checks accessor pairs in the given list of nodes.
* @param {ASTNode[]} nodes The list to check.
@ -182,11 +145,39 @@ module.exports = {
* @private
*/
function checkList(nodes, shouldCheck) {
const accessors = nodes
.filter(shouldCheck)
.filter(isAccessorKind)
.map(createAccessorData)
.reduce(mergeAccessorData, []);
const accessors = [];
let found = false;
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (shouldCheck(node) && isAccessorKind(node)) {
// Creates a new `AccessorData` object for the given getter or setter node.
const name = astUtils.getStaticPropertyName(node);
const key = (name !== null) ? name : sourceCode.getTokens(node.key);
// Merges the given `AccessorData` object into the given accessors list.
for (let j = 0; j < accessors.length; j++) {
const accessor = accessors[j];
if (areEqualKeys(accessor.key, key)) {
accessor.getters.push(...node.kind === "get" ? [node] : []);
accessor.setters.push(...node.kind === "set" ? [node] : []);
found = true;
break;
}
}
if (!found) {
accessors.push({
key,
getters: node.kind === "get" ? [node] : [],
setters: node.kind === "set" ? [node] : []
});
}
found = false;
}
}
for (const { getters, setters } of accessors) {

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Require `for-in` loops to include an `if` statement",
recommended: false,
url: "https://eslint.org/docs/rules/guard-for-in"
url: "https://eslint.org/docs/latest/rules/guard-for-in"
},
schema: [],

View file

@ -22,7 +22,7 @@ module.exports = {
docs: {
description: "Require error handling in callbacks",
recommended: false,
url: "https://eslint.org/docs/rules/handle-callback-err"
url: "https://eslint.org/docs/latest/rules/handle-callback-err"
},
schema: [
@ -38,6 +38,7 @@ module.exports = {
create(context) {
const errorArgument = context.options[0] || "err";
const sourceCode = context.sourceCode;
/**
* Checks if the given argument should be interpreted as a regexp pattern.
@ -79,7 +80,7 @@ module.exports = {
* @returns {void}
*/
function checkForError(node) {
const scope = context.getScope(),
const scope = sourceCode.getScope(node),
parameters = getParameters(scope),
firstParameter = parameters[0];

View file

@ -121,7 +121,7 @@ module.exports = {
docs: {
description: "Disallow specified identifiers",
recommended: false,
url: "https://eslint.org/docs/rules/id-blacklist"
url: "https://eslint.org/docs/latest/rules/id-blacklist"
},
schema: {
@ -140,6 +140,7 @@ module.exports = {
const denyList = new Set(context.options);
const reportedNodes = new Set();
const sourceCode = context.sourceCode;
let globalScope;
@ -231,8 +232,8 @@ module.exports = {
return {
Program() {
globalScope = context.getScope();
Program(node) {
globalScope = sourceCode.getScope(node);
},
Identifier(node) {

View file

@ -101,7 +101,7 @@ module.exports = {
docs: {
description: "Disallow specified identifiers",
recommended: false,
url: "https://eslint.org/docs/rules/id-denylist"
url: "https://eslint.org/docs/latest/rules/id-denylist"
},
schema: {
@ -121,6 +121,7 @@ module.exports = {
const denyList = new Set(context.options);
const reportedNodes = new Set();
const sourceCode = context.sourceCode;
let globalScope;
@ -210,8 +211,8 @@ module.exports = {
return {
Program() {
globalScope = context.getScope();
Program(node) {
globalScope = sourceCode.getScope(node);
},
[[

View file

@ -9,41 +9,8 @@
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const GraphemeSplitter = require("grapheme-splitter");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Checks if the string given as argument is ASCII or not.
* @param {string} value A string that you want to know if it is ASCII or not.
* @returns {boolean} `true` if `value` is ASCII string.
*/
function isASCII(value) {
if (typeof value !== "string") {
return false;
}
return /^[\u0020-\u007f]*$/u.test(value);
}
/** @type {GraphemeSplitter | undefined} */
let splitter;
/**
* Gets the length of the string. If the string is not in ASCII, counts graphemes.
* @param {string} value A string that you want to get the length.
* @returns {number} The length of `value`.
*/
function getStringLength(value) {
if (isASCII(value)) {
return value.length;
}
if (!splitter) {
splitter = new GraphemeSplitter();
}
return splitter.countGraphemes(value);
}
const { getGraphemeCount } = require("../shared/string-utils");
//------------------------------------------------------------------------------
// Rule Definition
@ -57,7 +24,7 @@ module.exports = {
docs: {
description: "Enforce minimum and maximum identifier lengths",
recommended: false,
url: "https://eslint.org/docs/rules/id-length"
url: "https://eslint.org/docs/latest/rules/id-length"
},
schema: [
@ -169,7 +136,7 @@ module.exports = {
const name = node.name;
const parent = node.parent;
const nameLength = getStringLength(name);
const nameLength = getGraphemeCount(name);
const isShort = nameLength < minLength;
const isLong = nameLength > maxLength;

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Require identifiers to match a specified regular expression",
recommended: false,
url: "https://eslint.org/docs/rules/id-match"
url: "https://eslint.org/docs/latest/rules/id-match"
},
schema: [
@ -67,6 +67,7 @@ module.exports = {
onlyDeclarations = !!options.onlyDeclarations,
ignoreDestructuring = !!options.ignoreDestructuring;
const sourceCode = context.sourceCode;
let globalScope;
//--------------------------------------------------------------------------
@ -170,8 +171,8 @@ module.exports = {
return {
Program() {
globalScope = context.getScope();
Program(node) {
globalScope = sourceCode.getScope(node);
},
Identifier(node) {

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Enforce the location of arrow function bodies",
recommended: false,
url: "https://eslint.org/docs/rules/implicit-arrow-linebreak"
url: "https://eslint.org/docs/latest/rules/implicit-arrow-linebreak"
},
fixable: "whitespace",
@ -34,7 +34,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const option = context.options[0] || "beside";
/**

View file

@ -28,7 +28,7 @@ module.exports = {
docs: {
description: "Enforce consistent indentation",
recommended: false,
url: "https://eslint.org/docs/rules/indent-legacy"
url: "https://eslint.org/docs/latest/rules/indent-legacy"
},
deprecated: true,
@ -206,7 +206,7 @@ module.exports = {
ObjectExpression: 1
};
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
if (context.options.length) {
if (context.options[0] === "tab") {

View file

@ -12,8 +12,6 @@
// Requirements
//------------------------------------------------------------------------------
const { OrderedMap } = require("js-sdsl");
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
@ -125,43 +123,48 @@ const KNOWN_NODES = new Set([
/**
* A mutable balanced binary search tree that stores (key, value) pairs. The keys are numeric, and must be unique.
* This is intended to be a generic wrapper around a balanced binary search tree library, so that the underlying implementation
* A mutable map that stores (key, value) pairs. The keys are numeric indices, and must be unique.
* This is intended to be a generic wrapper around a map with non-negative integer keys, so that the underlying implementation
* can easily be swapped out.
*/
class BinarySearchTree {
class IndexMap {
/**
* Creates an empty tree
* Creates an empty map
* @param {number} maxKey The maximum key
*/
constructor() {
this._orderedMap = new OrderedMap();
this._orderedMapEnd = this._orderedMap.end();
constructor(maxKey) {
// Initializing the array with the maximum expected size avoids dynamic reallocations that could degrade performance.
this._values = Array(maxKey + 1);
}
/**
* Inserts an entry into the tree.
* Inserts an entry into the map.
* @param {number} key The entry's key
* @param {any} value The entry's value
* @returns {void}
*/
insert(key, value) {
this._orderedMap.setElement(key, value);
this._values[key] = value;
}
/**
* Finds the entry with the largest key less than or equal to the provided key
* Finds the value of the entry with the largest key less than or equal to the provided key
* @param {number} key The provided key
* @returns {{key: number, value: *}|null} The found entry, or null if no such entry exists.
* @returns {*|undefined} The value of the found entry, or undefined if no such entry exists.
*/
findLe(key) {
const iterator = this._orderedMap.reverseLowerBound(key);
findLastNotAfter(key) {
const values = this._values;
if (iterator.equals(this._orderedMapEnd)) {
return {};
for (let index = key; index >= 0; index--) {
const value = values[index];
if (value) {
return value;
}
}
return { key: iterator.pointer[0], value: iterator.pointer[1] };
return void 0;
}
/**
@ -171,26 +174,7 @@ class BinarySearchTree {
* @returns {void}
*/
deleteRange(start, end) {
// Exit without traversing the tree if the range has zero size.
if (start === end) {
return;
}
const iterator = this._orderedMap.lowerBound(start);
if (iterator.equals(this._orderedMapEnd)) {
return;
}
if (end > this._orderedMap.back()[0]) {
while (!iterator.equals(this._orderedMapEnd)) {
this._orderedMap.eraseElementByIterator(iterator);
}
} else {
while (iterator.pointer[0] < end) {
this._orderedMap.eraseElementByIterator(iterator);
}
}
this._values.fill(void 0, start, end);
}
}
@ -204,15 +188,19 @@ class TokenInfo {
*/
constructor(sourceCode) {
this.sourceCode = sourceCode;
this.firstTokensByLineNumber = sourceCode.tokensAndComments.reduce((map, token) => {
if (!map.has(token.loc.start.line)) {
map.set(token.loc.start.line, token);
this.firstTokensByLineNumber = new Map();
const tokens = sourceCode.tokensAndComments;
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];
if (!this.firstTokensByLineNumber.has(token.loc.start.line)) {
this.firstTokensByLineNumber.set(token.loc.start.line, token);
}
if (!map.has(token.loc.end.line) && sourceCode.text.slice(token.range[1] - token.loc.end.column, token.range[1]).trim()) {
map.set(token.loc.end.line, token);
if (!this.firstTokensByLineNumber.has(token.loc.end.line) && sourceCode.text.slice(token.range[1] - token.loc.end.column, token.range[1]).trim()) {
this.firstTokensByLineNumber.set(token.loc.end.line, token);
}
return map;
}, new Map());
}
}
/**
@ -252,14 +240,15 @@ class OffsetStorage {
* @param {TokenInfo} tokenInfo a TokenInfo instance
* @param {number} indentSize The desired size of each indentation level
* @param {string} indentType The indentation character
* @param {number} maxIndex The maximum end index of any token
*/
constructor(tokenInfo, indentSize, indentType) {
constructor(tokenInfo, indentSize, indentType, maxIndex) {
this._tokenInfo = tokenInfo;
this._indentSize = indentSize;
this._indentType = indentType;
this._tree = new BinarySearchTree();
this._tree.insert(0, { offset: 0, from: null, force: false });
this._indexMap = new IndexMap(maxIndex);
this._indexMap.insert(0, { offset: 0, from: null, force: false });
this._lockedFirstTokens = new WeakMap();
this._desiredIndentCache = new WeakMap();
@ -267,7 +256,7 @@ class OffsetStorage {
}
_getOffsetDescriptor(token) {
return this._tree.findLe(token.range[0]).value;
return this._indexMap.findLastNotAfter(token.range[0]);
}
/**
@ -388,37 +377,36 @@ class OffsetStorage {
* * key: 820, value: { offset: 1, from: bazToken }
*
* To find the offset descriptor for any given token, one needs to find the node with the largest key
* which is <= token.start. To make this operation fast, the nodes are stored in a balanced binary
* search tree indexed by key.
* which is <= token.start. To make this operation fast, the nodes are stored in a map indexed by key.
*/
const descriptorToInsert = { offset, from: fromToken, force };
const descriptorAfterRange = this._tree.findLe(range[1]).value;
const descriptorAfterRange = this._indexMap.findLastNotAfter(range[1]);
const fromTokenIsInRange = fromToken && fromToken.range[0] >= range[0] && fromToken.range[1] <= range[1];
const fromTokenDescriptor = fromTokenIsInRange && this._getOffsetDescriptor(fromToken);
// First, remove any existing nodes in the range from the tree.
this._tree.deleteRange(range[0] + 1, range[1]);
// First, remove any existing nodes in the range from the map.
this._indexMap.deleteRange(range[0] + 1, range[1]);
// Insert a new node into the tree for this range
this._tree.insert(range[0], descriptorToInsert);
// Insert a new node into the map for this range
this._indexMap.insert(range[0], descriptorToInsert);
/*
* To avoid circular offset dependencies, keep the `fromToken` token mapped to whatever it was mapped to previously,
* even if it's in the current range.
*/
if (fromTokenIsInRange) {
this._tree.insert(fromToken.range[0], fromTokenDescriptor);
this._tree.insert(fromToken.range[1], descriptorToInsert);
this._indexMap.insert(fromToken.range[0], fromTokenDescriptor);
this._indexMap.insert(fromToken.range[1], descriptorToInsert);
}
/*
* To avoid modifying the offset of tokens after the range, insert another node to keep the offset of the following
* tokens the same as it was before.
*/
this._tree.insert(range[1], descriptorAfterRange);
this._indexMap.insert(range[1], descriptorAfterRange);
}
/**
@ -510,7 +498,7 @@ module.exports = {
docs: {
description: "Enforce consistent indentation",
recommended: false,
url: "https://eslint.org/docs/rules/indent"
url: "https://eslint.org/docs/latest/rules/indent"
},
fixable: "whitespace",
@ -703,9 +691,9 @@ module.exports = {
}
}
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const tokenInfo = new TokenInfo(sourceCode);
const offsets = new OffsetStorage(tokenInfo, indentSize, indentType === "space" ? " " : "\t");
const offsets = new OffsetStorage(tokenInfo, indentSize, indentType === "space" ? " " : "\t", sourceCode.text.length);
const parameterParens = new WeakSet();
/**
@ -980,19 +968,19 @@ module.exports = {
const parenStack = [];
const parenPairs = [];
tokens.forEach(nextToken => {
for (let i = 0; i < tokens.length; i++) {
const nextToken = tokens[i];
// Accumulate a list of parenthesis pairs
if (astUtils.isOpeningParenToken(nextToken)) {
parenStack.push(nextToken);
} else if (astUtils.isClosingParenToken(nextToken)) {
parenPairs.unshift({ left: parenStack.pop(), right: nextToken });
parenPairs.push({ left: parenStack.pop(), right: nextToken });
}
});
}
parenPairs.forEach(pair => {
const leftParen = pair.left;
const rightParen = pair.right;
for (let i = parenPairs.length - 1; i >= 0; i--) {
const leftParen = parenPairs[i].left;
const rightParen = parenPairs[i].right;
// We only want to handle parens around expressions, so exclude parentheses that are in function parameters and function call arguments.
if (!parameterParens.has(leftParen) && !parameterParens.has(rightParen)) {
@ -1006,7 +994,7 @@ module.exports = {
}
offsets.setDesiredOffset(rightParen, leftParen, 0);
});
}
}
/**
@ -1727,9 +1715,13 @@ module.exports = {
}
// Invoke the queued offset listeners for the nodes that aren't ignored.
listenerCallQueue
.filter(nodeInfo => !ignoredNodes.has(nodeInfo.node))
.forEach(nodeInfo => nodeInfo.listener(nodeInfo.node));
for (let i = 0; i < listenerCallQueue.length; i++) {
const nodeInfo = listenerCallQueue[i];
if (!ignoredNodes.has(nodeInfo.node)) {
nodeInfo.listener(nodeInfo.node);
}
}
// Update the offsets for ignored nodes to prevent their child tokens from being reported.
ignoredNodes.forEach(ignoreNode);
@ -1740,27 +1732,31 @@ module.exports = {
* Create a Map from (tokenOrComment) => (precedingToken).
* This is necessary because sourceCode.getTokenBefore does not handle a comment as an argument correctly.
*/
const precedingTokens = sourceCode.ast.comments.reduce((commentMap, comment) => {
const precedingTokens = new WeakMap();
for (let i = 0; i < sourceCode.ast.comments.length; i++) {
const comment = sourceCode.ast.comments[i];
const tokenOrCommentBefore = sourceCode.getTokenBefore(comment, { includeComments: true });
const hasToken = precedingTokens.has(tokenOrCommentBefore) ? precedingTokens.get(tokenOrCommentBefore) : tokenOrCommentBefore;
return commentMap.set(comment, commentMap.has(tokenOrCommentBefore) ? commentMap.get(tokenOrCommentBefore) : tokenOrCommentBefore);
}, new WeakMap());
precedingTokens.set(comment, hasToken);
}
sourceCode.lines.forEach((line, lineIndex) => {
const lineNumber = lineIndex + 1;
for (let i = 1; i < sourceCode.lines.length + 1; i++) {
if (!tokenInfo.firstTokensByLineNumber.has(lineNumber)) {
if (!tokenInfo.firstTokensByLineNumber.has(i)) {
// Don't check indentation on blank lines
return;
continue;
}
const firstTokenOfLine = tokenInfo.firstTokensByLineNumber.get(lineNumber);
const firstTokenOfLine = tokenInfo.firstTokensByLineNumber.get(i);
if (firstTokenOfLine.loc.start.line !== lineNumber) {
if (firstTokenOfLine.loc.start.line !== i) {
// Don't check the indentation of multi-line tokens (e.g. template literals or block comments) twice.
return;
continue;
}
if (astUtils.isCommentToken(firstTokenOfLine)) {
@ -1785,18 +1781,18 @@ module.exports = {
mayAlignWithBefore && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenBefore)) ||
mayAlignWithAfter && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenAfter))
) {
return;
continue;
}
}
// If the token matches the expected indentation, don't report it.
if (validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine))) {
return;
continue;
}
// Otherwise, report the token/comment.
report(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine));
});
}
}
}
);

View file

@ -50,7 +50,7 @@ module.exports = {
docs: {
description: "Require or disallow initialization in variable declarations",
recommended: false,
url: "https://eslint.org/docs/rules/init-declarations"
url: "https://eslint.org/docs/latest/rules/init-declarations"
},
schema: {

View file

@ -44,7 +44,7 @@ module.exports = {
docs: {
description: "Enforce the consistent use of either double or single quotes in JSX attributes",
recommended: false,
url: "https://eslint.org/docs/rules/jsx-quotes"
url: "https://eslint.org/docs/latest/rules/jsx-quotes"
},
fixable: "whitespace",

View file

@ -9,13 +9,7 @@
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
const GraphemeSplitter = require("grapheme-splitter");
const splitter = new GraphemeSplitter();
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const { getGraphemeCount } = require("../shared/string-utils");
/**
* Checks whether a string contains a line terminator as defined in
@ -144,7 +138,7 @@ module.exports = {
docs: {
description: "Enforce consistent spacing between keys and values in object literal properties",
recommended: false,
url: "https://eslint.org/docs/rules/key-spacing"
url: "https://eslint.org/docs/latest/rules/key-spacing"
},
fixable: "whitespace",
@ -332,7 +326,7 @@ module.exports = {
singleLineOptions = ruleOptions.singleLine,
alignmentOptions = ruleOptions.align || null;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Determines if the given property is key-value property.
@ -523,7 +517,7 @@ module.exports = {
const startToken = sourceCode.getFirstToken(property);
const endToken = getLastTokenBeforeColon(property.key);
return splitter.countGraphemes(sourceCode.getText().slice(startToken.range[0], endToken.range[1]));
return getGraphemeCount(sourceCode.getText().slice(startToken.range[0], endToken.range[1]));
}
/**

View file

@ -69,7 +69,7 @@ module.exports = {
docs: {
description: "Enforce consistent spacing before and after keywords",
recommended: false,
url: "https://eslint.org/docs/rules/keyword-spacing"
url: "https://eslint.org/docs/latest/rules/keyword-spacing"
},
fixable: "whitespace",
@ -108,7 +108,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const tokensToIgnore = new WeakSet();

View file

@ -18,7 +18,7 @@ module.exports = {
docs: {
description: "Enforce position of line comments",
recommended: false,
url: "https://eslint.org/docs/rules/line-comment-position"
url: "https://eslint.org/docs/latest/rules/line-comment-position"
},
schema: [
@ -78,7 +78,7 @@ module.exports = {
const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN;
const fallThroughRegExp = /^\s*falls?\s?through/u;
const customIgnoreRegExp = new RegExp(ignorePattern, "u");
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Public

View file

@ -23,7 +23,7 @@ module.exports = {
docs: {
description: "Enforce consistent linebreak style",
recommended: false,
url: "https://eslint.org/docs/rules/linebreak-style"
url: "https://eslint.org/docs/latest/rules/linebreak-style"
},
fixable: "whitespace",
@ -40,7 +40,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers

View file

@ -57,7 +57,7 @@ module.exports = {
docs: {
description: "Require empty lines around comments",
recommended: false,
url: "https://eslint.org/docs/rules/lines-around-comment"
url: "https://eslint.org/docs/latest/rules/lines-around-comment"
},
fixable: "whitespace",
@ -113,6 +113,10 @@ module.exports = {
},
applyDefaultIgnorePatterns: {
type: "boolean"
},
afterHashbangComment: {
type: "boolean",
default: false
}
},
additionalProperties: false
@ -134,7 +138,7 @@ module.exports = {
options.beforeBlockComment = typeof options.beforeBlockComment !== "undefined" ? options.beforeBlockComment : true;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const lines = sourceCode.lines,
numLines = lines.length + 1,
@ -449,6 +453,13 @@ module.exports = {
before: options.beforeBlockComment
});
}
} else if (token.type === "Shebang") {
if (options.afterHashbangComment) {
checkForEmptyLine(token, {
after: options.afterHashbangComment,
before: false
});
}
}
});
}

View file

@ -20,7 +20,7 @@ module.exports = {
docs: {
description: "Require or disallow newlines around directives",
recommended: false,
url: "https://eslint.org/docs/rules/lines-around-directive"
url: "https://eslint.org/docs/latest/rules/lines-around-directive"
},
schema: [{
@ -54,7 +54,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const config = context.options[0] || "always";
const expectLineBefore = typeof config === "string" ? config : config.before;
const expectLineAfter = typeof config === "string" ? config : config.after;

View file

@ -22,7 +22,7 @@ module.exports = {
docs: {
description: "Require or disallow an empty line between class members",
recommended: false,
url: "https://eslint.org/docs/rules/lines-between-class-members"
url: "https://eslint.org/docs/latest/rules/lines-between-class-members"
},
fixable: "whitespace",
@ -55,7 +55,7 @@ module.exports = {
options[0] = context.options[0] || "always";
options[1] = context.options[1] || { exceptAfterSingleLine: false };
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Gets a pair of tokens that should be used to check lines between two class member nodes.

View file

@ -112,7 +112,7 @@ function isBooleanCast(expression, scope) {
/**
* Returns true for:
* truthiness checks: value, Boolean(value), !!value
* falsyness checks: !value, !Boolean(value)
* falsiness checks: !value, !Boolean(value)
* nullish checks: value == null, value === undefined || value === null
* @param {ASTNode} expression Test condition
* @param {import('eslint-scope').Scope} scope Scope of the expression
@ -159,9 +159,9 @@ module.exports = {
type: "suggestion",
docs: {
description: "Require or disallow logical assignment logical operator shorthand",
description: "Require or disallow logical assignment operator shorthand",
recommended: false,
url: "https://eslint.org/docs/rules/logical-assignment-operators"
url: "https://eslint.org/docs/latest/rules/logical-assignment-operators"
},
schema: {
@ -188,7 +188,6 @@ module.exports = {
}]
},
fixable: "code",
// eslint-disable-next-line eslint-plugin/require-meta-has-suggestions -- Does not detect conditional suggestions
hasSuggestions: true,
messages: {
assignment: "Assignment (=) can be replaced with operator assignment ({{operator}}).",
@ -205,8 +204,8 @@ module.exports = {
create(context) {
const mode = context.options[0] === "never" ? "never" : "always";
const checkIf = mode === "always" && context.options.length > 1 && context.options[1].enforceForIfStatements;
const sourceCode = context.getSourceCode();
const isStrict = context.getScope().isStrict;
const sourceCode = context.sourceCode;
const isStrict = sourceCode.getScope(sourceCode.ast).isStrict;
/**
* Returns false if the access could be a getter
@ -371,8 +370,11 @@ module.exports = {
return;
}
const requiresOuterParenthesis = logical.parent.type !== "ExpressionStatement" &&
(astUtils.getPrecedence({ type: "AssignmentExpression" }) < astUtils.getPrecedence(logical.parent));
const parentPrecedence = astUtils.getPrecedence(logical.parent);
const requiresOuterParenthesis = logical.parent.type !== "ExpressionStatement" && (
parentPrecedence === -1 ||
astUtils.getPrecedence({ type: "AssignmentExpression" }) < parentPrecedence
);
if (!astUtils.isParenthesised(sourceCode, logical) && requiresOuterParenthesis) {
yield ruleFixer.insertTextBefore(logical, "(");
@ -409,7 +411,7 @@ module.exports = {
}
const body = hasBody ? ifNode.consequent.body[0] : ifNode.consequent;
const scope = context.getScope();
const scope = sourceCode.getScope(ifNode);
const existence = getExistence(ifNode.test, scope);
if (

View file

@ -21,7 +21,7 @@ module.exports = {
docs: {
description: "Enforce a maximum number of classes per file",
recommended: false,
url: "https://eslint.org/docs/rules/max-classes-per-file"
url: "https://eslint.org/docs/latest/rules/max-classes-per-file"
},
schema: [

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Enforce a maximum depth that blocks can be nested",
recommended: false,
url: "https://eslint.org/docs/rules/max-depth"
url: "https://eslint.org/docs/latest/rules/max-depth"
},
schema: [

View file

@ -71,7 +71,7 @@ module.exports = {
docs: {
description: "Enforce a maximum line length",
recommended: false,
url: "https://eslint.org/docs/rules/max-len"
url: "https://eslint.org/docs/latest/rules/max-len"
},
schema: [
@ -97,7 +97,7 @@ module.exports = {
*/
const URL_REGEXP = /[^:/?#]:\/\/[^?#]/u;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Computes the length of a line that may contain tabs. The width of each
@ -252,19 +252,23 @@ module.exports = {
return sourceCode.ast.tokens.filter(token => token.type === "RegularExpression");
}
/**
* A reducer to group an AST node by line number, both start and end.
* @param {Object} acc the accumulator
* @param {ASTNode} node the AST node in question
* @returns {Object} the modified accumulator
* @private
*
* reduce an array of AST nodes by line number, both start and end.
* @param {ASTNode[]} arr array of AST nodes
* @returns {Object} accululated AST nodes
*/
function groupByLineNumber(acc, node) {
for (let i = node.loc.start.line; i <= node.loc.end.line; ++i) {
ensureArrayAndPush(acc, i, node);
function groupArrayByLineNumber(arr) {
const obj = {};
for (let i = 0; i < arr.length; i++) {
const node = arr[i];
for (let j = node.loc.start.line; j <= node.loc.end.line; ++j) {
ensureArrayAndPush(obj, j, node);
}
}
return acc;
return obj;
}
/**
@ -312,13 +316,13 @@ module.exports = {
let commentsIndex = 0;
const strings = getAllStrings();
const stringsByLine = strings.reduce(groupByLineNumber, {});
const stringsByLine = groupArrayByLineNumber(strings);
const templateLiterals = getAllTemplateLiterals();
const templateLiteralsByLine = templateLiterals.reduce(groupByLineNumber, {});
const templateLiteralsByLine = groupArrayByLineNumber(templateLiterals);
const regExpLiterals = getAllRegExpLiterals();
const regExpLiteralsByLine = regExpLiterals.reduce(groupByLineNumber, {});
const regExpLiteralsByLine = groupArrayByLineNumber(regExpLiterals);
lines.forEach((line, i) => {

View file

@ -73,7 +73,7 @@ module.exports = {
docs: {
description: "Enforce a maximum number of lines of code in a function",
recommended: false,
url: "https://eslint.org/docs/rules/max-lines-per-function"
url: "https://eslint.org/docs/latest/rules/max-lines-per-function"
},
schema: [
@ -85,7 +85,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const lines = sourceCode.lines;
const option = context.options[0];

View file

@ -36,7 +36,7 @@ module.exports = {
docs: {
description: "Enforce a maximum number of lines per file",
recommended: false,
url: "https://eslint.org/docs/rules/max-lines"
url: "https://eslint.org/docs/latest/rules/max-lines"
},
schema: [
@ -87,7 +87,7 @@ module.exports = {
const skipComments = option && option.skipComments;
const skipBlankLines = option && option.skipBlankLines;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Returns whether or not a token is a comment node type

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Enforce a maximum depth that callbacks can be nested",
recommended: false,
url: "https://eslint.org/docs/rules/max-nested-callbacks"
url: "https://eslint.org/docs/latest/rules/max-nested-callbacks"
},
schema: [

View file

@ -24,7 +24,7 @@ module.exports = {
docs: {
description: "Enforce a maximum number of parameters in function definitions",
recommended: false,
url: "https://eslint.org/docs/rules/max-params"
url: "https://eslint.org/docs/latest/rules/max-params"
},
schema: [
@ -57,7 +57,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const option = context.options[0];
let numParams = 3;

View file

@ -22,7 +22,7 @@ module.exports = {
docs: {
description: "Enforce a maximum number of statements allowed per line",
recommended: false,
url: "https://eslint.org/docs/rules/max-statements-per-line"
url: "https://eslint.org/docs/latest/rules/max-statements-per-line"
},
schema: [
@ -45,7 +45,7 @@ module.exports = {
create(context) {
const sourceCode = context.getSourceCode(),
const sourceCode = context.sourceCode,
options = context.options[0] || {},
maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1;

View file

@ -24,7 +24,7 @@ module.exports = {
docs: {
description: "Enforce a maximum number of statements allowed in function blocks",
recommended: false,
url: "https://eslint.org/docs/rules/max-statements"
url: "https://eslint.org/docs/latest/rules/max-statements"
},
schema: [

View file

@ -18,11 +18,41 @@ module.exports = {
docs: {
description: "Enforce a particular style for multiline comments",
recommended: false,
url: "https://eslint.org/docs/rules/multiline-comment-style"
url: "https://eslint.org/docs/latest/rules/multiline-comment-style"
},
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: {
expectedBlock: "Expected a block comment instead of consecutive line comments.",
expectedBareBlock: "Expected a block comment without padding stars.",
@ -35,8 +65,10 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const option = context.options[0] || "starred-block";
const params = context.options[1] || {};
const checkJSDoc = !!params.checkJSDoc;
//----------------------------------------------------------------------
// Helpers
@ -333,11 +365,18 @@ module.exports = {
"separate-lines"(commentGroup) {
const [firstComment] = commentGroup;
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 });
if (tokenAfter && firstComment.loc.end.line === tokenAfter.loc.start.line) {

View file

@ -19,7 +19,7 @@ module.exports = {
docs: {
description: "Enforce newlines between operands of ternary expressions",
recommended: false,
url: "https://eslint.org/docs/rules/multiline-ternary"
url: "https://eslint.org/docs/latest/rules/multiline-ternary"
},
schema: [
@ -39,7 +39,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
const option = context.options[0];
const multiline = option !== "never";
const allowSingleLine = option === "always-multiline";

View file

@ -84,7 +84,7 @@ module.exports = {
docs: {
description: "Require constructor names to begin with a capital letter",
recommended: false,
url: "https://eslint.org/docs/rules/new-cap"
url: "https://eslint.org/docs/latest/rules/new-cap"
},
schema: [
@ -147,7 +147,7 @@ module.exports = {
const listeners = {};
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers

View file

@ -27,24 +27,15 @@ module.exports = {
docs: {
description: "Enforce or disallow parentheses when invoking a constructor with no arguments",
recommended: false,
url: "https://eslint.org/docs/rules/new-parens"
url: "https://eslint.org/docs/latest/rules/new-parens"
},
fixable: "code",
schema: {
anyOf: [
{
type: "array",
items: [
{
enum: ["always", "never"]
}
],
minItems: 0,
maxItems: 1
}
]
},
schema: [
{
enum: ["always", "never"]
}
],
messages: {
missing: "Missing '()' invoking a constructor.",
unnecessary: "Unnecessary '()' invoking a constructor with no arguments."
@ -55,7 +46,7 @@ module.exports = {
const options = context.options;
const always = options[0] !== "never"; // Default is always
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
return {
NewExpression(node) {

View file

@ -24,7 +24,7 @@ module.exports = {
docs: {
description: "Require or disallow an empty line after variable declarations",
recommended: false,
url: "https://eslint.org/docs/rules/newline-after-var"
url: "https://eslint.org/docs/latest/rules/newline-after-var"
},
schema: [
{
@ -43,7 +43,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
// Default `mode` to "always".
const mode = context.options[0] === "never" ? "never" : "always";
@ -212,7 +212,6 @@ module.exports = {
context.report({
node,
messageId: "unexpected",
data: { identifier: node.name },
fix(fixer) {
const linesBetween = sourceCode.getText().slice(lastToken.range[1], nextToken.range[0]).split(astUtils.LINEBREAK_MATCHER);
@ -231,7 +230,6 @@ module.exports = {
context.report({
node,
messageId: "expected",
data: { identifier: node.name },
fix(fixer) {
if ((noNextLineToken ? getLastCommentLineOfBlock(nextLineNum) : lastToken.loc.end.line) === nextToken.loc.start.line) {
return fixer.insertTextBefore(nextToken, "\n\n");

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Require an empty line before `return` statements",
recommended: false,
url: "https://eslint.org/docs/rules/newline-before-return"
url: "https://eslint.org/docs/latest/rules/newline-before-return"
},
fixable: "whitespace",
@ -31,7 +31,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers

View file

@ -20,7 +20,7 @@ module.exports = {
docs: {
description: "Require a newline after each call in a method chain",
recommended: false,
url: "https://eslint.org/docs/rules/newline-per-chained-call"
url: "https://eslint.org/docs/latest/rules/newline-per-chained-call"
},
fixable: "whitespace",
@ -47,7 +47,7 @@ module.exports = {
const options = context.options[0] || {},
ignoreChainWithDepth = options.ignoreChainWithDepth || 2;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Get the prefix of a given MemberExpression node.

View file

@ -90,7 +90,7 @@ module.exports = {
docs: {
description: "Disallow the use of `alert`, `confirm`, and `prompt`",
recommended: false,
url: "https://eslint.org/docs/rules/no-alert"
url: "https://eslint.org/docs/latest/rules/no-alert"
},
schema: [],
@ -101,10 +101,12 @@ module.exports = {
},
create(context) {
const sourceCode = context.sourceCode;
return {
CallExpression(node) {
const callee = skipChainExpression(node.callee),
currentScope = context.getScope();
currentScope = sourceCode.getScope(node);
// without window.
if (callee.type === "Identifier") {

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Disallow `Array` constructors",
recommended: false,
url: "https://eslint.org/docs/rules/no-array-constructor"
url: "https://eslint.org/docs/latest/rules/no-array-constructor"
},
schema: [],

View file

@ -16,7 +16,7 @@ module.exports = {
docs: {
description: "Disallow using an async function as a Promise executor",
recommended: true,
url: "https://eslint.org/docs/rules/no-async-promise-executor"
url: "https://eslint.org/docs/latest/rules/no-async-promise-executor"
},
fixable: null,
@ -30,7 +30,7 @@ module.exports = {
return {
"NewExpression[callee.name='Promise'][arguments.0.async=true]"(node) {
context.report({
node: context.getSourceCode().getFirstToken(node.arguments[0], token => token.value === "async"),
node: context.sourceCode.getFirstToken(node.arguments[0], token => token.value === "async"),
messageId: "async"
});
}

View file

@ -61,7 +61,7 @@ module.exports = {
docs: {
description: "Disallow `await` inside of loops",
recommended: false,
url: "https://eslint.org/docs/rules/no-await-in-loop"
url: "https://eslint.org/docs/latest/rules/no-await-in-loop"
},
schema: [],

View file

@ -28,7 +28,7 @@ module.exports = {
docs: {
description: "Disallow bitwise operators",
recommended: false,
url: "https://eslint.org/docs/rules/no-bitwise"
url: "https://eslint.org/docs/latest/rules/no-bitwise"
},
schema: [

View file

@ -21,7 +21,7 @@ module.exports = {
docs: {
description: "Disallow use of the `Buffer()` constructor",
recommended: false,
url: "https://eslint.org/docs/rules/no-buffer-constructor"
url: "https://eslint.org/docs/latest/rules/no-buffer-constructor"
},
schema: [],

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Disallow the use of `arguments.caller` or `arguments.callee`",
recommended: false,
url: "https://eslint.org/docs/rules/no-caller"
url: "https://eslint.org/docs/latest/rules/no-caller"
},
schema: [],

View file

@ -16,7 +16,7 @@ module.exports = {
docs: {
description: "Disallow lexical declarations in case clauses",
recommended: true,
url: "https://eslint.org/docs/rules/no-case-declarations"
url: "https://eslint.org/docs/latest/rules/no-case-declarations"
},
schema: [],

View file

@ -24,7 +24,7 @@ module.exports = {
docs: {
description: "Disallow `catch` clause parameters from shadowing variables in the outer scope",
recommended: false,
url: "https://eslint.org/docs/rules/no-catch-shadow"
url: "https://eslint.org/docs/latest/rules/no-catch-shadow"
},
replacedBy: ["no-shadow"],
@ -39,6 +39,8 @@ module.exports = {
create(context) {
const sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
@ -60,7 +62,7 @@ module.exports = {
return {
"CatchClause[param!=null]"(node) {
let scope = context.getScope();
let scope = sourceCode.getScope(node);
/*
* When ecmaVersion >= 6, CatchClause creates its own scope

View file

@ -19,7 +19,7 @@ module.exports = {
docs: {
description: "Disallow reassigning class members",
recommended: true,
url: "https://eslint.org/docs/rules/no-class-assign"
url: "https://eslint.org/docs/latest/rules/no-class-assign"
},
schema: [],
@ -31,6 +31,8 @@ module.exports = {
create(context) {
const sourceCode = context.sourceCode;
/**
* Finds and reports references that are non initializer and writable.
* @param {Variable} variable A variable to check.
@ -49,7 +51,7 @@ module.exports = {
* @returns {void}
*/
function checkForClass(node) {
context.getDeclaredVariables(node).forEach(checkVariable);
sourceCode.getDeclaredVariables(node).forEach(checkVariable);
}
return {

View file

@ -16,7 +16,7 @@ module.exports = {
docs: {
description: "Disallow comparing against -0",
recommended: true,
url: "https://eslint.org/docs/rules/no-compare-neg-zero"
url: "https://eslint.org/docs/latest/rules/no-compare-neg-zero"
},
fixable: null,

View file

@ -36,7 +36,7 @@ module.exports = {
docs: {
description: "Disallow assignment operators in conditional expressions",
recommended: true,
url: "https://eslint.org/docs/rules/no-cond-assign"
url: "https://eslint.org/docs/latest/rules/no-cond-assign"
},
schema: [
@ -57,7 +57,7 @@ module.exports = {
const prohibitAssign = (context.options[0] || "except-parens");
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**
* Check whether an AST node is the test expression for a conditional statement.

View file

@ -33,7 +33,7 @@ module.exports = {
docs: {
description: "Disallow arrow functions where they could be confused with comparisons",
recommended: false,
url: "https://eslint.org/docs/rules/no-confusing-arrow"
url: "https://eslint.org/docs/latest/rules/no-confusing-arrow"
},
fixable: "code",
@ -56,7 +56,7 @@ module.exports = {
const config = context.options[0] || {};
const allowParens = config.allowParens || (config.allowParens === void 0);
const onlyOneSimpleParam = config.onlyOneSimpleParam;
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
/**

View file

@ -23,7 +23,7 @@ module.exports = {
docs: {
description: "Disallow the use of `console`",
recommended: false,
url: "https://eslint.org/docs/rules/no-console"
url: "https://eslint.org/docs/latest/rules/no-console"
},
schema: [
@ -51,6 +51,7 @@ module.exports = {
create(context) {
const options = context.options[0] || {};
const allowed = options.allow || [];
const sourceCode = context.sourceCode;
/**
* Checks whether the given reference is 'console' or not.
@ -109,8 +110,8 @@ module.exports = {
}
return {
"Program:exit"() {
const scope = context.getScope();
"Program:exit"(node) {
const scope = sourceCode.getScope(node);
const consoleVar = astUtils.getVariableByName(scope, "console");
const shadowed = consoleVar && consoleVar.defs.length > 0;

View file

@ -19,7 +19,7 @@ module.exports = {
docs: {
description: "Disallow reassigning `const` variables",
recommended: true,
url: "https://eslint.org/docs/rules/no-const-assign"
url: "https://eslint.org/docs/latest/rules/no-const-assign"
},
schema: [],
@ -31,6 +31,8 @@ module.exports = {
create(context) {
const sourceCode = context.sourceCode;
/**
* Finds and reports references that are non initializer and writable.
* @param {Variable} variable A variable to check.
@ -45,7 +47,7 @@ module.exports = {
return {
VariableDeclaration(node) {
if (node.kind === "const") {
context.getDeclaredVariables(node).forEach(checkVariable);
sourceCode.getDeclaredVariables(node).forEach(checkVariable);
}
}
};

View file

@ -14,6 +14,23 @@ const NUMERIC_OR_STRING_BINARY_OPERATORS = new Set(["+", "-", "*", "/", "%", "|"
// Helpers
//------------------------------------------------------------------------------
/**
* 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,
* it will always resolve to a constant value of either: `null`, `undefined`
@ -21,9 +38,14 @@ const NUMERIC_OR_STRING_BINARY_OPERATORS = new Set(["+", "-", "*", "/", "%", "|"
* three states at runtime would return `false`.
* @param {Scope} scope The scope in which the node was found.
* @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) {
case "ObjectExpression": // Objects are never nullish
case "ArrayExpression": // Arrays are never nullish
@ -45,9 +67,12 @@ function hasConstantNullishness(scope, node) {
return (functionName === "Boolean" || functionName === "String" || functionName === "Number") &&
isReferenceToGlobalVariable(scope, node.callee);
}
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);
}
/*
@ -80,7 +105,7 @@ function hasConstantNullishness(scope, node) {
case "SequenceExpression": {
const last = node.expressions[node.expressions.length - 1];
return hasConstantNullishness(scope, last);
return hasConstantNullishness(scope, last, nonNullish);
}
case "Identifier":
return node.name === "undefined" && isReferenceToGlobalVariable(scope, node);
@ -348,7 +373,7 @@ function isAlwaysNew(scope, node) {
* user-defined constructors could return a sentinel
* object.
*
* 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.
*/
return Object.hasOwnProperty.call(globals.builtin, node.callee.name) &&
@ -378,24 +403,6 @@ function isAlwaysNew(scope, node) {
}
}
/**
* 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.
* @param {Scope} scope Scope in which the expression was found.
@ -407,14 +414,14 @@ function isNullOrUndefined(scope, node) {
function findBinaryExpressionConstantOperand(scope, a, b, operator) {
if (operator === "==" || operator === "!=") {
if (
(isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b)) ||
(isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b, false)) ||
(isStaticBoolean(scope, a) && hasConstantLooseBooleanComparison(scope, b))
) {
return b;
}
} else if (operator === "===" || operator === "!==") {
if (
(isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b)) ||
(isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b, false)) ||
(isStaticBoolean(scope, a) && hasConstantStrictBooleanComparison(scope, b))
) {
return b;
@ -434,7 +441,7 @@ module.exports = {
docs: {
description: "Disallow expressions where the operation doesn't affect the value",
recommended: false,
url: "https://eslint.org/docs/rules/no-constant-binary-expression"
url: "https://eslint.org/docs/latest/rules/no-constant-binary-expression"
},
schema: [],
messages: {
@ -446,19 +453,21 @@ module.exports = {
},
create(context) {
const sourceCode = context.sourceCode;
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 } });
}
},
BinaryExpression(node) {
const scope = context.getScope();
const scope = sourceCode.getScope(node);
const { right, left, operator } = node;
const rightConstantOperand = findBinaryExpressionConstantOperand(scope, left, right, operator);
const leftConstantOperand = findBinaryExpressionConstantOperand(scope, right, left, operator);

View file

@ -23,7 +23,7 @@ module.exports = {
docs: {
description: "Disallow constant expressions in conditions",
recommended: true,
url: "https://eslint.org/docs/rules/no-constant-condition"
url: "https://eslint.org/docs/latest/rules/no-constant-condition"
},
schema: [
@ -48,6 +48,7 @@ module.exports = {
const options = context.options[0] || {},
checkLoops = options.checkLoops !== false,
loopSetStack = [];
const sourceCode = context.sourceCode;
let loopsInCurrentScope = new Set();
@ -62,7 +63,7 @@ module.exports = {
* @private
*/
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);
}
}
@ -87,7 +88,7 @@ module.exports = {
* @private
*/
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" });
}
}

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Disallow returning value from constructor",
recommended: false,
url: "https://eslint.org/docs/rules/no-constructor-return"
url: "https://eslint.org/docs/latest/rules/no-constructor-return"
},
schema: {},

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Disallow `continue` statements",
recommended: false,
url: "https://eslint.org/docs/rules/no-continue"
url: "https://eslint.org/docs/latest/rules/no-continue"
},
schema: [],

View file

@ -5,7 +5,7 @@
"use strict";
const RegExpValidator = require("regexpp").RegExpValidator;
const RegExpValidator = require("@eslint-community/regexpp").RegExpValidator;
const collector = new (class {
constructor() {
this._source = "";
@ -56,7 +56,7 @@ module.exports = {
docs: {
description: "Disallow control characters in regular expressions",
recommended: true,
url: "https://eslint.org/docs/rules/no-control-regex"
url: "https://eslint.org/docs/latest/rules/no-control-regex"
},
schema: [],

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Disallow the use of `debugger`",
recommended: true,
url: "https://eslint.org/docs/rules/no-debugger"
url: "https://eslint.org/docs/latest/rules/no-debugger"
},
fixable: null,

View file

@ -17,7 +17,7 @@ module.exports = {
docs: {
description: "Disallow deleting variables",
recommended: true,
url: "https://eslint.org/docs/rules/no-delete-var"
url: "https://eslint.org/docs/latest/rules/no-delete-var"
},
schema: [],

View file

@ -15,9 +15,9 @@ module.exports = {
type: "suggestion",
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,
url: "https://eslint.org/docs/rules/no-div-regex"
url: "https://eslint.org/docs/latest/rules/no-div-regex"
},
fixable: "code",
@ -30,7 +30,7 @@ module.exports = {
},
create(context) {
const sourceCode = context.getSourceCode();
const sourceCode = context.sourceCode;
return {

Some files were not shown because too many files have changed in this diff Show more