UNPKG

@putout/plugin-remove-unused-expressions

Version:

🐊Putout plugin adds ability to find and remove unused expressions

105 lines (73 loc) 2.61 kB
import {types, operator} from 'putout'; const {remove, isSimple} = operator; const { isReturnStatement, isBlockStatement, } = types; export const report = () => 'Avoid unused expression statements'; export const fix = (path) => { remove(path); }; export const traverse = ({push}) => ({ DirectiveLiteral(path) { if (path.node.value === 'use strict') return; if (path.node.value === 'use client') return; push(path.parentPath); }, ExpressionStatement(path) { const expressionPath = path.get('expression'); if (isPrevReturnWithoutArg(path)) return; if (isUselessLogical(expressionPath)) return push(expressionPath); if (expressionPath.isIdentifier()) return push(expressionPath); if (expressionPath.isObjectExpression()) return push(expressionPath); if (expressionPath.isArrayExpression()) return push(expressionPath); if (expressionPath.isMemberExpression()) return push(expressionPath); if (isNotDirectiveLiteral(expressionPath)) return push(expressionPath); if (expressionPath.isUnaryExpression({operator: '!'}) && !isIIFE(expressionPath)) return push(expressionPath); }, }); function isIIFE(path) { const argPath = path.get('argument'); if (!argPath.isCallExpression()) return false; const calleePath = argPath.get('callee'); return calleePath.isFunction(); } function isNotDirectiveLiteral(path) { if (!path.isLiteral()) return false; if (!path.isStringLiteral({value: 'use strict'})) return true; const {parentPath} = path; const isDirective = parentPath === parentPath.parentPath.get('body.0'); return !isDirective; } function isUselessLogical(path) { if (!path.isLogicalExpression()) return false; const left = path.get('left'); const right = path.get('right'); return isSimple(left) && isSimple(right); } function isPrevReturnWithoutArg(path) { const prevPath = path.getPrevSibling(); if (isReturnStatement(prevPath)) return !prevPath.node.argument; const {parentPath} = path; if (parentPath.isLabeledStatement()) { const blockPath = parentPath.parentPath; if (isBlockStatement(blockPath)) return isPrevReturnWithoutArg(blockPath); } return false; }