securityos/node_modules/eslint-plugin-unicorn/rules/utils/needs-semicolon.js

115 lines
2.1 KiB
JavaScript
Raw Permalink Normal View History

2024-09-06 15:32:35 +00:00
'use strict';
// https://github.com/eslint/espree/blob/6b7d0b8100537dcd5c84a7fb17bbe28edcabe05d/lib/token-translator.js#L20
const tokenTypesNeedsSemicolon = new Set([
'String',
'Null',
'Boolean',
'Numeric',
'RegularExpression',
]);
const charactersMightNeedsSemicolon = new Set([
'[',
'(',
'/',
'`',
'+',
'-',
'*',
',',
'.',
]);
/**
Determines if a semicolon needs to be inserted before `code`, in order to avoid a SyntaxError.
@param {Token} tokenBefore Token before `code`.
@param {SourceCode} sourceCode
@param {String} [code] Code text to determine.
@returns {boolean} `true` if a semicolon needs to be inserted before `code`.
*/
function needsSemicolon(tokenBefore, sourceCode, code) {
if (
code === ''
|| (code && !charactersMightNeedsSemicolon.has(code.charAt(0)))
) {
return false;
}
if (!tokenBefore) {
return false;
}
const {type, value, range} = tokenBefore;
const lastBlockNode = sourceCode.getNodeByRangeIndex(range[0]);
if (type === 'Punctuator') {
if (value === ';') {
return false;
}
if (value === ']') {
return true;
}
if (value === ')') {
switch (lastBlockNode.type) {
case 'IfStatement': {
if (sourceCode.getTokenBefore(lastBlockNode.consequent) === tokenBefore) {
return false;
}
break;
}
case 'ForStatement':
case 'ForInStatement':
case 'ForOfStatement':
case 'WhileStatement':
case 'DoWhileStatement':
case 'WithStatement': {
if (lastBlockNode.body && sourceCode.getTokenBefore(lastBlockNode.body) === tokenBefore) {
return false;
}
break;
}
// No default
}
return true;
}
}
if (tokenTypesNeedsSemicolon.has(type)) {
return true;
}
if (type === 'Template') {
return value.endsWith('`');
}
if (lastBlockNode.type === 'ObjectExpression') {
return true;
}
if (type === 'Identifier') {
// `for...of`
if (value === 'of' && lastBlockNode.type === 'ForOfStatement') {
return false;
}
// `await`
if (value === 'await' && lastBlockNode.type === 'AwaitExpression') {
return false;
}
return true;
}
return false;
}
module.exports = needsSemicolon;