securityos/node_modules/eslint-plugin-unicorn/rules/no-unnecessary-await.js

108 lines
2.6 KiB
JavaScript

'use strict';
const {
addParenthesizesToReturnOrThrowExpression,
removeSpacesAfter,
} = require('./fix/index.js');
const {isParenthesized} = require('./utils/parentheses.js');
const needsSemicolon = require('./utils/needs-semicolon.js');
const isOnSameLine = require('./utils/is-on-same-line.js');
const MESSAGE_ID = 'no-unnecessary-await';
const messages = {
[MESSAGE_ID]: 'Do not `await` non-promise value.',
};
function notPromise(node) {
switch (node.type) {
case 'ArrayExpression':
case 'ArrowFunctionExpression':
case 'AwaitExpression':
case 'BinaryExpression':
case 'ClassExpression':
case 'FunctionExpression':
case 'JSXElement':
case 'JSXFragment':
case 'Literal':
case 'TemplateLiteral':
case 'UnaryExpression':
case 'UpdateExpression': {
return true;
}
case 'SequenceExpression': {
return notPromise(node.expressions[node.expressions.length - 1]);
}
// No default
}
return false;
}
/** @param {import('eslint').Rule.RuleContext} context */
const create = context => ({
AwaitExpression(node) {
if (!notPromise(node.argument)) {
return;
}
const sourceCode = context.getSourceCode();
const awaitToken = sourceCode.getFirstToken(node);
const problem = {
node,
loc: awaitToken.loc,
messageId: MESSAGE_ID,
};
const valueNode = node.argument;
if (
// Removing `await` may change them to a declaration, if there is no `id` will cause SyntaxError
valueNode.type === 'FunctionExpression'
|| valueNode.type === 'ClassExpression'
// `+await +1` -> `++1`
|| (
node.parent.type === 'UnaryExpression'
&& valueNode.type === 'UnaryExpression'
&& node.parent.operator === valueNode.operator
)
) {
return problem;
}
return Object.assign(problem, {
/** @param {import('eslint').Rule.RuleFixer} fixer */
* fix(fixer) {
if (
!isOnSameLine(awaitToken, valueNode)
&& !isParenthesized(node, sourceCode)
) {
yield * addParenthesizesToReturnOrThrowExpression(fixer, node.parent, sourceCode);
}
yield fixer.remove(awaitToken);
yield removeSpacesAfter(awaitToken, sourceCode, fixer);
const nextToken = sourceCode.getTokenAfter(awaitToken);
const tokenBefore = sourceCode.getTokenBefore(awaitToken);
if (needsSemicolon(tokenBefore, sourceCode, nextToken.value)) {
yield fixer.insertTextBefore(nextToken, ';');
}
},
});
},
});
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
create,
meta: {
type: 'suggestion',
docs: {
description: 'Disallow awaiting non-promise values.',
},
fixable: 'code',
messages,
},
};