tools: update ESLint to 7.2.0

Update ESLint to 7.2.0

PR-URL: https://github.com/nodejs/node/pull/33776
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
This commit is contained in:
cjihrig
2020-06-06 16:18:25 -04:00
parent 7b46793eee
commit 85fbf7175e
43 changed files with 311 additions and 117 deletions

View File

@@ -15,7 +15,7 @@ function main({ n, context, count, rest, method }) {
for (let n = 0; n < count; n++)
src[`p${n}`] = n;
let obj; // eslint-disable-line no-unused-vars
let obj;
switch (method) {
case '_extend':
@@ -33,7 +33,7 @@ function main({ n, context, count, rest, method }) {
case 'spread':
bench.start();
for (let i = 0; i < n; i++)
obj = { ...src };
obj = { ...src }; // eslint-disable-line no-unused-vars
bench.end(n);
break;
default:

View File

@@ -15,13 +15,12 @@ const makeDuplexPair = require('../common/duplexpair');
let { clientSide } = makeDuplexPair();
let clientTLS = new TLSSocket(clientSide, { isServer: false });
// eslint-disable-next-line no-unused-vars
let clientTLSHandle = clientTLS._handle;
setImmediate(() => {
clientTLS = null;
global.gc();
clientTLSHandle = null;
clientTLSHandle = null; // eslint-disable-line no-unused-vars
global.gc();
setImmediate(() => {
clientSide = null;

View File

@@ -250,8 +250,8 @@ The following companies, organizations, and individuals support ESLint's ongoing
<!--sponsorsstart-->
<h3>Gold Sponsors</h3>
<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/e780cd4/logo.png" alt="Shopify" height="96"></a> <a href="https://www.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://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://bruce.agency"><img src="https://images.opencollective.com/brucemade/0c70c59/logo.png" alt="Bruce" height="32"></a> <a href="https://edubirdie.com/"><img src="https://images.opencollective.com/edubirdie2/b1d51ab/logo.png" alt="EduBirdie" height="32"></a> <a href="https://www.casinotop.com/"><img src="https://images.opencollective.com/casinotop-com/10fd95b/logo.png" alt="CasinoTop.com" height="32"></a> <a href="https://www.casinotopp.net/"><img src="https://images.opencollective.com/casino-topp/1dd399a/logo.png" alt="Casino Topp" height="32"></a> <a href="https://writersperhour.com/urgent-essay-writing-service"><img src="https://images.opencollective.com/writersperhour/5787d4b/logo.png" alt="Writers Per Hour" 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://cooltechzone.com/netflix-vpn"><img src="https://images.opencollective.com/vpn-netflix/4850160/logo.png" alt="vpn netflix" height="32"></a> <a href="https://www.kasinot.fi"><img src="https://images.opencollective.com/kasinot-fi/e09aa2e/logo.png" alt="Kasinot.fi" height="32"></a> <a href="https://www.pelisivut.com"><img src="https://images.opencollective.com/pelisivut/04f08f2/logo.png" alt="Pelisivut" height="32"></a> <a href="https://www.nettikasinot.org"><img src="https://images.opencollective.com/nettikasinot-org/bbd887f/logo.png" alt="Nettikasinot.org" height="32"></a> <a href="https://www.bonus.com.de/freispiele"><img src="https://images.opencollective.com/bonusfinder-deutschland/646169e/logo.png" alt="BonusFinder Deutschland" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" 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://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
<p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://bruce.agency"><img src="https://images.opencollective.com/brucemade/0c70c59/logo.png" alt="Bruce" height="32"></a> <a href="https://edubirdie.com/"><img src="https://images.opencollective.com/edubirdie2/b1d51ab/logo.png" alt="EduBirdie" height="32"></a> <a href="https://www.casinotop.com/"><img src="https://images.opencollective.com/casinotop-com/10fd95b/logo.png" alt="CasinoTop.com" height="32"></a> <a href="https://www.casinotopp.net/"><img src="https://images.opencollective.com/casino-topp/1dd399a/logo.png" alt="Casino Topp" height="32"></a> <a href="https://writersperhour.com/write-my-essay"><img src="https://images.opencollective.com/writersperhour/5787d4b/logo.png" alt="Writers Per Hour" 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://cooltechzone.com/netflix-vpn"><img src="https://images.opencollective.com/vpn-netflix/4850160/logo.png" alt="vpn netflix" height="32"></a> <a href="https://www.kasinot.fi"><img src="https://images.opencollective.com/kasinot-fi/e09aa2e/logo.png" alt="Kasinot.fi" height="32"></a> <a href="https://www.pelisivut.com"><img src="https://images.opencollective.com/pelisivut/04f08f2/logo.png" alt="Pelisivut" height="32"></a> <a href="https://www.nettikasinot.org"><img src="https://images.opencollective.com/nettikasinot-org/bbd887f/logo.png" alt="Nettikasinot.org" height="32"></a> <a href="https://www.bonus.com.de/freispiele"><img src="https://images.opencollective.com/bonusfinder-deutschland/646169e/logo.png" alt="BonusFinder Deutschland" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" 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://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
<!--sponsorsend-->
## <a name="technology-sponsors"></a>Technology Sponsors

View File

@@ -403,7 +403,7 @@ function getCacheFile(cacheFile, cwd) {
try {
fileStats = fs.lstatSync(resolvedCacheFile);
} catch (ex) {
} catch {
fileStats = null;
}
@@ -991,7 +991,7 @@ class CLIEngine {
const npmFormat = naming.normalizePackageName(normalizedFormatName, "eslint-formatter");
formatterPath = ModuleResolver.resolve(npmFormat, path.join(cwd, "__placeholder__.js"));
} catch (e) {
} catch {
formatterPath = path.resolve(__dirname, "formatters", normalizedFormatName);
}
}

View File

@@ -517,7 +517,7 @@ class ConfigArrayFactory {
try {
loadPackageJSONConfigFile(filePath);
return filePath;
} catch (error) { /* ignore */ }
} catch { /* ignore */ }
} else {
return filePath;
}

View File

@@ -265,11 +265,7 @@ function processAnswers(answers) {
};
config.parserOptions.ecmaVersion = espree.latestEcmaVersion;
config.env.es6 = true;
config.globals = {
Atomics: "readonly",
SharedArrayBuffer: "readonly"
};
config.env.es2020 = true;
// set the module type
if (answers.moduleType === "esm") {
@@ -350,7 +346,7 @@ function getLocalESLintVersion() {
const eslint = require(eslintPath);
return eslint.linter.version || null;
} catch (_err) {
} catch {
return null;
}
}

View File

@@ -33,10 +33,10 @@ function isCaseNode(node) {
* Checks whether the given logical operator is taken into account for the code
* path analysis.
* @param {string} operator The operator found in the LogicalExpression node
* @returns {boolean} `true` if the operator is "&&" or "||"
* @returns {boolean} `true` if the operator is "&&" or "||" or "??"
*/
function isHandledLogicalOperator(operator) {
return operator === "&&" || operator === "||";
return operator === "&&" || operator === "||" || operator === "??";
}
/**

View File

@@ -201,6 +201,7 @@ function finalizeTestSegmentsOfFor(context, choiceContext, head) {
if (!choiceContext.processed) {
choiceContext.trueForkContext.add(head);
choiceContext.falseForkContext.add(head);
choiceContext.qqForkContext.add(head);
}
if (context.test !== true) {
@@ -351,6 +352,7 @@ class CodePathState {
isForkingAsResult,
trueForkContext: ForkContext.newEmpty(this.forkContext),
falseForkContext: ForkContext.newEmpty(this.forkContext),
qqForkContext: ForkContext.newEmpty(this.forkContext),
processed: false
};
}
@@ -370,6 +372,7 @@ class CodePathState {
switch (context.kind) {
case "&&":
case "||":
case "??":
/*
* If any result were not transferred from child contexts,
@@ -379,6 +382,7 @@ class CodePathState {
if (!context.processed) {
context.trueForkContext.add(headSegments);
context.falseForkContext.add(headSegments);
context.qqForkContext.add(headSegments);
}
/*
@@ -390,6 +394,7 @@ class CodePathState {
parentContext.trueForkContext.addAll(context.trueForkContext);
parentContext.falseForkContext.addAll(context.falseForkContext);
parentContext.qqForkContext.addAll(context.qqForkContext);
parentContext.processed = true;
return context;
@@ -456,13 +461,24 @@ class CodePathState {
* This got segments already from the child choice context.
* Creates the next path from own true/false fork context.
*/
const prevForkContext =
context.kind === "&&" ? context.trueForkContext
/* kind === "||" */ : context.falseForkContext;
let prevForkContext;
switch (context.kind) {
case "&&": // if true then go to the right-hand side.
prevForkContext = context.trueForkContext;
break;
case "||": // if false then go to the right-hand side.
prevForkContext = context.falseForkContext;
break;
case "??": // Both true/false can short-circuit, so needs the third path to go to the right-hand side. That's qqForkContext.
prevForkContext = context.qqForkContext;
break;
default:
throw new Error("unreachable");
}
forkContext.replaceHead(prevForkContext.makeNext(0, -1));
prevForkContext.clear();
context.processed = false;
} else {
@@ -471,14 +487,19 @@ class CodePathState {
* So addresses the head segments.
* The head segments are the path of the left-hand operand.
*/
if (context.kind === "&&") {
// The path does short-circuit if false.
context.falseForkContext.add(forkContext.head);
} else {
// The path does short-circuit if true.
context.trueForkContext.add(forkContext.head);
switch (context.kind) {
case "&&": // the false path can short-circuit.
context.falseForkContext.add(forkContext.head);
break;
case "||": // the true path can short-circuit.
context.trueForkContext.add(forkContext.head);
break;
case "??": // both can short-circuit.
context.trueForkContext.add(forkContext.head);
context.falseForkContext.add(forkContext.head);
break;
default:
throw new Error("unreachable");
}
forkContext.replaceHead(forkContext.makeNext(-1, -1));
@@ -501,6 +522,7 @@ class CodePathState {
if (!context.processed) {
context.trueForkContext.add(forkContext.head);
context.falseForkContext.add(forkContext.head);
context.qqForkContext.add(forkContext.head);
}
context.processed = false;

View File

@@ -78,7 +78,7 @@ module.exports = class ConfigCommentParser {
config: items
};
}
} catch (ex) {
} catch {
debug("Levn parsing failed; falling back to manual parsing.");

View File

@@ -116,7 +116,13 @@ module.exports = {
if (never && hasWhitespace) {
context.report({
node,
loc: leftToken.loc.start,
loc: {
start: leftToken.loc.end,
end: {
line: rightToken.loc.start.line,
column: rightToken.loc.start.column - 1
}
},
messageId: "unexpectedWhitespace",
fix(fixer) {
@@ -134,7 +140,13 @@ module.exports = {
} else if (!never && !hasWhitespace) {
context.report({
node,
loc: leftToken.loc.start,
loc: {
start: {
line: leftToken.loc.end.line,
column: leftToken.loc.end.column - 1
},
end: rightToken.loc.start
},
messageId: "missing",
fix(fixer) {
return fixer.insertTextBefore(rightToken, " ");
@@ -143,7 +155,10 @@ module.exports = {
} else if (!never && !allowNewlines && hasNewline) {
context.report({
node,
loc: leftToken.loc.start,
loc: {
start: leftToken.loc.end,
end: rightToken.loc.start
},
messageId: "unexpectedNewline",
fix(fixer) {
return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ");

View File

@@ -152,7 +152,7 @@ module.exports = {
sourceCode.isSpaceBetweenTokens(prevToken, token)
) {
context.report({
loc: token.loc.start,
loc: { start: prevToken.loc.end, end: token.loc.start },
messageId: "unexpectedBefore",
data: token,
fix(fixer) {
@@ -203,8 +203,9 @@ module.exports = {
astUtils.isTokenOnSameLine(token, nextToken) &&
sourceCode.isSpaceBetweenTokens(token, nextToken)
) {
context.report({
loc: token.loc.start,
loc: { start: token.loc.end, end: nextToken.loc.start },
messageId: "unexpectedAfter",
data: token,
fix(fixer) {
@@ -442,6 +443,12 @@ module.exports = {
checkSpacingAround(sourceCode.getTokenAfter(firstToken));
}
if (node.type === "ExportAllDeclaration" && node.exported) {
const asToken = sourceCode.getTokenBefore(node.exported);
checkSpacingBefore(asToken, PREV_TOKEN_M);
}
if (node.source) {
const fromToken = sourceCode.getTokenBefore(node.source);

View File

@@ -39,25 +39,7 @@ module.exports = {
const option = context.options[0];
const multiline = option !== "never";
const allowSingleLine = option === "always-multiline";
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
* Tests whether node is preceded by supplied tokens
* @param {ASTNode} node node to check
* @param {ASTNode} parentNode parent of node to report
* @param {boolean} expected whether newline was expected or not
* @returns {void}
* @private
*/
function reportError(node, parentNode, expected) {
context.report({
node,
messageId: `${expected ? "expected" : "unexpected"}${node === parentNode.test ? "TestCons" : "ConsAlt"}`
});
}
const sourceCode = context.getSourceCode();
//--------------------------------------------------------------------------
// Public
@@ -65,16 +47,39 @@ module.exports = {
return {
ConditionalExpression(node) {
const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(node.test, node.consequent);
const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(node.consequent, node.alternate);
const questionToken = sourceCode.getTokenAfter(node.test, astUtils.isNotClosingParenToken);
const colonToken = sourceCode.getTokenAfter(node.consequent, astUtils.isNotClosingParenToken);
const firstTokenOfTest = sourceCode.getFirstToken(node);
const lastTokenOfTest = sourceCode.getTokenBefore(questionToken);
const firstTokenOfConsequent = sourceCode.getTokenAfter(questionToken);
const lastTokenOfConsequent = sourceCode.getTokenBefore(colonToken);
const firstTokenOfAlternate = sourceCode.getTokenAfter(colonToken);
const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, firstTokenOfConsequent);
const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, firstTokenOfAlternate);
if (!multiline) {
if (!areTestAndConsequentOnSameLine) {
reportError(node.test, node, false);
context.report({
node: node.test,
loc: {
start: firstTokenOfTest.loc.start,
end: lastTokenOfTest.loc.end
},
messageId: "unexpectedTestCons"
});
}
if (!areConsequentAndAlternateOnSameLine) {
reportError(node.consequent, node, false);
context.report({
node: node.consequent,
loc: {
start: firstTokenOfConsequent.loc.start,
end: lastTokenOfConsequent.loc.end
},
messageId: "unexpectedConsAlt"
});
}
} else {
if (allowSingleLine && node.loc.start.line === node.loc.end.line) {
@@ -82,11 +87,25 @@ module.exports = {
}
if (areTestAndConsequentOnSameLine) {
reportError(node.test, node, true);
context.report({
node: node.test,
loc: {
start: firstTokenOfTest.loc.start,
end: lastTokenOfTest.loc.end
},
messageId: "expectedTestCons"
});
}
if (areConsequentAndAlternateOnSameLine) {
reportError(node.consequent, node, true);
context.report({
node: node.consequent,
loc: {
start: firstTokenOfConsequent.loc.start,
end: lastTokenOfConsequent.loc.end
},
messageId: "expectedConsAlt"
});
}
}
}

View File

@@ -35,7 +35,7 @@ const collector = new (class {
try {
this._source = regexpStr;
this._validator.validatePattern(regexpStr); // Call onCharacter hook
} catch (err) {
} catch {
// Ignore syntax errors in RegExp.
}

View File

@@ -172,6 +172,9 @@ module.exports = {
case "UnaryExpression":
return precedence(node) < precedence(parent);
case "LogicalExpression":
if (astUtils.isMixedLogicalAndCoalesceExpressions(node, parent)) {
return true;
}
if (previousNode === parent.left) {
return precedence(node) < precedence(parent);
}

View File

@@ -51,7 +51,8 @@ module.exports = {
ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] },
enforceForArrowConditionals: { type: "boolean" },
enforceForSequenceExpressions: { type: "boolean" },
enforceForNewInMemberExpressions: { type: "boolean" }
enforceForNewInMemberExpressions: { type: "boolean" },
enforceForFunctionPrototypeMethods: { type: "boolean" }
},
additionalProperties: false
}
@@ -83,12 +84,28 @@ module.exports = {
context.options[1].enforceForSequenceExpressions === false;
const IGNORE_NEW_IN_MEMBER_EXPR = ALL_NODES && context.options[1] &&
context.options[1].enforceForNewInMemberExpressions === false;
const IGNORE_FUNCTION_PROTOTYPE_METHODS = ALL_NODES && context.options[1] &&
context.options[1].enforceForFunctionPrototypeMethods === false;
const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" });
const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" });
let reportsBuffer;
/**
* Determines whether the given node is a `call` or `apply` method call, invoked directly on a `FunctionExpression` node.
* Example: function(){}.call()
* @param {ASTNode} node The node to be checked.
* @returns {boolean} True if the node is an immediate `call` or `apply` method call.
* @private
*/
function isImmediateFunctionPrototypeMethodCall(node) {
return node.type === "CallExpression" &&
node.callee.type === "MemberExpression" &&
node.callee.object.type === "FunctionExpression" &&
["call", "apply"].includes(astUtils.getStaticPropertyName(node.callee));
}
/**
* Determines if this rule should be enforced for a node given the current configuration.
* @param {ASTNode} node The node to be checked.
@@ -125,6 +142,10 @@ module.exports = {
return false;
}
if (isImmediateFunctionPrototypeMethodCall(node) && IGNORE_FUNCTION_PROTOTYPE_METHODS) {
return false;
}
return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
}
@@ -478,6 +499,7 @@ module.exports = {
if (!shouldSkipLeft && hasExcessParens(node.left)) {
if (
!(node.left.type === "UnaryExpression" && isExponentiation) &&
!astUtils.isMixedLogicalAndCoalesceExpressions(node.left, node) &&
(leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation)) ||
isParenthesisedTwice(node.left)
) {
@@ -487,6 +509,7 @@ module.exports = {
if (!shouldSkipRight && hasExcessParens(node.right)) {
if (
!astUtils.isMixedLogicalAndCoalesceExpressions(node.right, node) &&
(rightPrecedence > prec || (rightPrecedence === prec && isExponentiation)) ||
isParenthesisedTwice(node.right)
) {
@@ -927,7 +950,12 @@ module.exports = {
LogicalExpression: checkBinaryLogical,
MemberExpression(node) {
const nodeObjHasExcessParens = hasExcessParens(node.object);
const nodeObjHasExcessParens = hasExcessParens(node.object) &&
!(
isImmediateFunctionPrototypeMethodCall(node.parent) &&
node.parent.callee === node &&
IGNORE_FUNCTION_PROTOTYPE_METHODS
);
if (
nodeObjHasExcessParens &&

View File

@@ -93,7 +93,7 @@ module.exports = {
try {
validator.validateFlags(flags);
return null;
} catch (err) {
} catch {
return `Invalid flags supplied to RegExp constructor '${flags}'`;
}
}

View File

@@ -147,7 +147,7 @@ module.exports = {
pattern.length,
flags.includes("u")
);
} catch (e) {
} catch {
// Ignore regular expressions with syntax errors
return;

View File

@@ -21,13 +21,15 @@ const COMPARISON_OPERATORS = ["==", "!=", "===", "!==", ">", ">=", "<", "<="];
const LOGICAL_OPERATORS = ["&&", "||"];
const RELATIONAL_OPERATORS = ["in", "instanceof"];
const TERNARY_OPERATOR = ["?:"];
const COALESCE_OPERATOR = ["??"];
const ALL_OPERATORS = [].concat(
ARITHMETIC_OPERATORS,
BITWISE_OPERATORS,
COMPARISON_OPERATORS,
LOGICAL_OPERATORS,
RELATIONAL_OPERATORS,
TERNARY_OPERATOR
TERNARY_OPERATOR,
COALESCE_OPERATOR
);
const DEFAULT_GROUPS = [
ARITHMETIC_OPERATORS,
@@ -236,7 +238,6 @@ module.exports = {
return {
BinaryExpression: check,
LogicalExpression: check
};
}
};

View File

@@ -67,7 +67,7 @@ module.exports = {
* or the reverse before non-tab/-space
* characters begin.
*/
let regex = /^(?=[\t ]*(\t | \t))/u;
let regex = /^(?=( +|\t+))\1(?:\t| )/u;
if (smartTabs) {
@@ -75,19 +75,27 @@ module.exports = {
* At least one space followed by a tab
* before non-tab/-space characters begin.
*/
regex = /^(?=[\t ]* \t)/u;
regex = /^(?=(\t*))\1(?=( +))\2\t/u;
}
lines.forEach((line, i) => {
const match = regex.exec(line);
if (match) {
const lineNumber = i + 1,
column = match.index + 1,
loc = { line: lineNumber, column };
const lineNumber = i + 1;
const loc = {
start: {
line: lineNumber,
column: match[0].length - 2
},
end: {
line: lineNumber,
column: match[0].length
}
};
if (!ignoredCommentLines.has(lineNumber)) {
const containingNode = sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc(loc));
const containingNode = sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc(loc.start));
if (!(containingNode && ["Literal", "TemplateElement"].includes(containingNode.type))) {
context.report({

View File

@@ -76,7 +76,7 @@ module.exports = {
try {
regExpAST = regExpParser.parsePattern(pattern, 0, pattern.length, flags.includes("u"));
} catch (e) {
} catch {
// Ignore regular expressions with syntax errors
return;

View File

@@ -61,6 +61,12 @@ module.exports = {
}
return {
ExportAllDeclaration(node) {
if (node.exported) {
checkExportedName(node.exported);
}
},
ExportNamedDeclaration(node) {
const declaration = node.declaration;

View File

@@ -147,10 +147,12 @@ module.exports = {
loc: node.consequent.loc.start,
messageId: "unnecessaryConditionalAssignment",
fix: fixer => {
const shouldParenthesizeAlternate = (
astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE &&
!astUtils.isParenthesised(sourceCode, node.alternate)
);
const shouldParenthesizeAlternate =
(
astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE ||
astUtils.isCoalesceExpression(node.alternate)
) &&
!astUtils.isParenthesised(sourceCode, node.alternate);
const alternateText = shouldParenthesizeAlternate
? `(${sourceCode.getText(node.alternate)})`
: astUtils.getParenthesisedText(sourceCode, node.alternate);

View File

@@ -124,7 +124,7 @@ module.exports = {
return true;
}
return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/u.test(node.type) ||
return /^(?:Assignment|Call|New|Update|Yield|Await|Import)Expression$/u.test(node.type) ||
(node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0);
}

View File

@@ -619,7 +619,9 @@ module.exports = {
// Report the first declaration.
if (unusedVar.defs.length > 0) {
context.report({
node: unusedVar.identifiers[0],
node: unusedVar.references.length ? unusedVar.references[
unusedVar.references.length - 1
].identifier : unusedVar.identifiers[0],
messageId: "unusedVar",
data: unusedVar.references.some(ref => ref.isWrite())
? getAssignedMessageData(unusedVar)

View File

@@ -95,7 +95,7 @@ module.exports = {
try {
regExpAST = parser.parsePattern(pattern, 0, pattern.length, flags.includes("u"));
} catch (e) {
} catch {
// Ignore regular expressions with syntax errors
return;

View File

@@ -59,7 +59,7 @@ module.exports = {
try {
ast = parser.parsePattern(pattern, 0, pattern.length, uFlag);
} catch (_) {
} catch {
// ignore regex syntax errors
return;

View File

@@ -154,7 +154,7 @@ module.exports = {
try {
tokens = espree.tokenize(key.value);
} catch (e) {
} catch {
return;
}
@@ -239,7 +239,7 @@ module.exports = {
try {
tokens = espree.tokenize(key.value);
} catch (e) {
} catch {
necessaryQuotes = true;
return;
}

View File

@@ -49,7 +49,10 @@ module.exports = {
if (never && hasWhitespace) {
context.report({
node,
loc: tagToken.loc.start,
loc: {
start: tagToken.loc.end,
end: literalToken.loc.start
},
messageId: "unexpected",
fix(fixer) {
const comments = sourceCode.getCommentsBefore(node.quasi);
@@ -68,7 +71,10 @@ module.exports = {
} else if (!never && !hasWhitespace) {
context.report({
node,
loc: tagToken.loc.start,
loc: {
start: node.loc.start,
end: literalToken.loc.start
},
messageId: "missing",
fix(fixer) {
return fixer.insertTextAfter(tagToken, " ");

View File

@@ -416,6 +416,53 @@ function equalTokens(left, right, sourceCode) {
return true;
}
/**
* Check if the given node is a true logical expression or not.
*
* The three binary expressions logical-or (`||`), logical-and (`&&`), and
* coalesce (`??`) are known as `ShortCircuitExpression`.
* But ESTree represents those by `LogicalExpression` node.
*
* This function rejects coalesce expressions of `LogicalExpression` node.
* @param {ASTNode} node The node to check.
* @returns {boolean} `true` if the node is `&&` or `||`.
* @see https://tc39.es/ecma262/#prod-ShortCircuitExpression
*/
function isLogicalExpression(node) {
return (
node.type === "LogicalExpression" &&
(node.operator === "&&" || node.operator === "||")
);
}
/**
* Check if the given node is a nullish coalescing expression or not.
*
* The three binary expressions logical-or (`||`), logical-and (`&&`), and
* coalesce (`??`) are known as `ShortCircuitExpression`.
* But ESTree represents those by `LogicalExpression` node.
*
* This function finds only coalesce expressions of `LogicalExpression` node.
* @param {ASTNode} node The node to check.
* @returns {boolean} `true` if the node is `??`.
*/
function isCoalesceExpression(node) {
return node.type === "LogicalExpression" && node.operator === "??";
}
/**
* Check if given two nodes are the pair of a logical expression and a coalesce expression.
* @param {ASTNode} left A node to check.
* @param {ASTNode} right Another node to check.
* @returns {boolean} `true` if the two nodes are the pair of a logical expression and a coalesce expression.
*/
function isMixedLogicalAndCoalesceExpressions(left, right) {
return (
(isLogicalExpression(left) && isCoalesceExpression(right)) ||
(isCoalesceExpression(left) && isLogicalExpression(right))
);
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
@@ -779,6 +826,7 @@ module.exports = {
case "LogicalExpression":
switch (node.operator) {
case "||":
case "??":
return 4;
case "&&":
return 5;
@@ -1415,7 +1463,7 @@ module.exports = {
try {
tokens = espree.tokenize(leftValue, espreeOptions);
} catch (e) {
} catch {
return false;
}
@@ -1444,7 +1492,7 @@ module.exports = {
try {
tokens = espree.tokenize(rightValue, espreeOptions);
} catch (e) {
} catch {
return false;
}
@@ -1538,5 +1586,9 @@ module.exports = {
*/
hasOctalEscapeSequence(rawString) {
return OCTAL_ESCAPE_PATTERN.test(rawString);
}
},
isLogicalExpression,
isCoalesceExpression,
isMixedLogicalAndCoalesceExpressions
};

View File

@@ -29,7 +29,7 @@ function getMarkerLines(loc, source, opts) {
column: 0,
line: -1
}, loc.start);
const endLoc = Object.assign({}, startLoc, {}, loc.end);
const endLoc = Object.assign(Object.assign({}, startLoc), loc.end);
const {
linesAbove = 2,
linesBelow = 3

View File

@@ -3,9 +3,12 @@
"name": "Sebastian McKenzie",
"email": "sebmck@gmail.com"
},
"bugs": {
"url": "https://github.com/babel/babel/issues"
},
"bundleDependencies": false,
"dependencies": {
"@babel/highlight": "^7.8.3"
"@babel/highlight": "^7.10.1"
},
"deprecated": false,
"description": "Generate errors that contain a code frame that point to source locations.",
@@ -13,7 +16,7 @@
"chalk": "^2.0.0",
"strip-ansi": "^4.0.0"
},
"gitHead": "a7620bd266ae1345975767bbc7abf09034437017",
"gitHead": "88f57a7ea659d25232bf62de1efceb5d6299b8cf",
"homepage": "https://babeljs.io/",
"license": "MIT",
"main": "lib/index.js",
@@ -23,7 +26,8 @@
},
"repository": {
"type": "git",
"url": "https://github.com/babel/babel/tree/master/packages/babel-code-frame"
"url": "git+https://github.com/babel/babel.git",
"directory": "packages/babel-code-frame"
},
"version": "7.8.3"
"version": "7.10.1"
}

View File

@@ -1,4 +1,7 @@
{
"bugs": {
"url": "https://github.com/babel/babel/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Validate identifier/keywords name",
@@ -7,7 +10,8 @@
"unicode-13.0.0": "^0.8.0"
},
"exports": "./lib/index.js",
"gitHead": "5b97e77e030cf3853a147fdff81844ea4026219d",
"gitHead": "88f57a7ea659d25232bf62de1efceb5d6299b8cf",
"homepage": "https://github.com/babel/babel#readme",
"license": "MIT",
"main": "./lib/index.js",
"name": "@babel/helper-validator-identifier",
@@ -16,7 +20,8 @@
},
"repository": {
"type": "git",
"url": "https://github.com/babel/babel/tree/master/packages/babel-helper-validator-identifier"
"url": "git+https://github.com/babel/babel.git",
"directory": "packages/babel-helper-validator-identifier"
},
"version": "7.9.5"
"version": "7.10.1"
}

View File

@@ -3,9 +3,12 @@
"name": "suchipi",
"email": "me@suchipi.com"
},
"bugs": {
"url": "https://github.com/babel/babel/issues"
},
"bundleDependencies": false,
"dependencies": {
"@babel/helper-validator-identifier": "^7.9.0",
"@babel/helper-validator-identifier": "^7.10.1",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
},
@@ -14,7 +17,7 @@
"devDependencies": {
"strip-ansi": "^4.0.0"
},
"gitHead": "8d5e422be27251cfaadf8dd2536b31b4a5024b02",
"gitHead": "88f57a7ea659d25232bf62de1efceb5d6299b8cf",
"homepage": "https://babeljs.io/",
"license": "MIT",
"main": "lib/index.js",
@@ -24,7 +27,8 @@
},
"repository": {
"type": "git",
"url": "https://github.com/babel/babel/tree/master/packages/babel-highlight"
"url": "git+https://github.com/babel/babel.git",
"directory": "packages/babel-highlight"
},
"version": "7.9.0"
"version": "7.10.1"
}

View File

@@ -2,9 +2,10 @@
const path = require('path');
const which = require('which');
const pathKey = require('path-key')();
const getPathKey = require('path-key');
function resolveCommandAttempt(parsed, withoutPathExt) {
const env = parsed.options.env || process.env;
const cwd = process.cwd();
const hasCustomCwd = parsed.options.cwd != null;
// Worker threads do not have process.chdir()
@@ -24,7 +25,7 @@ function resolveCommandAttempt(parsed, withoutPathExt) {
try {
resolved = which.sync(parsed.command, {
path: (parsed.options.env || process.env)[pathKey],
path: env[getPathKey({ env })],
pathExt: withoutPathExt ? path.delimiter : undefined,
});
} catch (e) {

View File

@@ -77,5 +77,5 @@
"release": "standard-version",
"test": "jest --env node --coverage"
},
"version": "7.0.2"
"version": "7.0.3"
}

View File

@@ -593,15 +593,26 @@ class Referencer extends esrecurse.Visitor {
this.visitChildren(node);
}
// TODO: ExportDeclaration doesn't exist. for bc?
ExportDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportAllDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportDefaultDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportNamedDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportSpecifier(node) {
// TODO: `node.id` doesn't exist. for bc?
const local = (node.id || node.local);
this.visit(local);

View File

@@ -16,7 +16,8 @@
"eslint-config-eslint": "^5.0.1",
"eslint-plugin-node": "^9.1.0",
"eslint-release": "^1.0.0",
"espree": "^6.0.0",
"eslint-visitor-keys": "^1.2.0",
"espree": "^7.1.0",
"istanbul": "^0.4.5",
"mocha": "^6.1.4",
"npm-license": "^0.3.3",
@@ -48,5 +49,5 @@
"publish-release": "eslint-publish-release",
"test": "node Makefile.js test"
},
"version": "5.0.0"
"version": "5.1.0"
}

View File

@@ -66,6 +66,7 @@
],
"EmptyStatement": [],
"ExportAllDeclaration": [
"exported",
"source"
],
"ExportDefaultDeclaration": [

View File

@@ -44,5 +44,5 @@
"publish-release": "eslint-publish-release",
"test": "nyc mocha tests/lib"
},
"version": "1.1.0"
"version": "1.2.0"
}

View File

@@ -8,9 +8,9 @@
},
"bundleDependencies": false,
"dependencies": {
"acorn": "^7.1.1",
"acorn": "^7.2.0",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.1.0"
"eslint-visitor-keys": "^1.2.0"
},
"deprecated": false,
"description": "An Esprima-compatible JavaScript parser built on Acorn",
@@ -57,6 +57,7 @@
},
"scripts": {
"browserify": "node Makefile.js browserify",
"fixlint": "node Makefile.js lint --fix",
"generate-alpharelease": "eslint-generate-prerelease alpha",
"generate-betarelease": "eslint-generate-prerelease beta",
"generate-rcrelease": "eslint-generate-prerelease rc",
@@ -67,5 +68,5 @@
"sync-docs": "node Makefile.js docs",
"test": "npm run-script lint && node Makefile.js test"
},
"version": "7.0.0"
"version": "7.1.0"
}

View File

@@ -38,5 +38,5 @@
"posttest": "npm run lint",
"test": "tap test/*-test.js"
},
"version": "2.1.0"
"version": "2.1.1"
}

View File

@@ -272,7 +272,7 @@ class NativeCompileCache {
//------------------------------------------------------------------------------
function mkdirpSync(p_) {
_mkdirpSync(path.resolve(p_), parseInt('0777', 8) & ~process.umask());
_mkdirpSync(path.resolve(p_), 0o777);
}
function _mkdirpSync(p, mode) {

View File

@@ -18,10 +18,10 @@
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"eslint-plugin-markdown": "^1.0.2",
"eslint-scope": "^5.0.0",
"eslint-scope": "^5.1.0",
"eslint-utils": "^2.0.0",
"eslint-visitor-keys": "^1.1.0",
"espree": "^7.0.0",
"eslint-visitor-keys": "^1.2.0",
"espree": "^7.1.0",
"esquery": "^1.2.0",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
@@ -54,7 +54,7 @@
"devDependencies": {
"@babel/core": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"acorn": "^7.1.1",
"acorn": "^7.2.0",
"babel-loader": "^8.0.5",
"chai": "^4.0.1",
"cheerio": "^0.22.0",
@@ -153,5 +153,5 @@
"test:cli": "mocha",
"webpack": "node Makefile.js webpack"
},
"version": "7.1.0"
"version": "7.2.0"
}