UNPKG

@putout/plugin-remove-unused-variables

Version:

🐊Putout plugin adds ability to find and remove unused variables

149 lines (115 loc) 2.8 kB
import {types} from 'putout'; import getVars from './get-vars.js'; import { useParamsBeforeLastUsed, useParamsBeforeAssign, usePropertiesBeforeRest, } from './use-params.js'; const { isClassDeclaration, isFunctionDeclaration, } = types; export default (ast, opts) => { const vars = {}; const allParams = []; const {setPath, traverse} = opts; const use = useVariable({ vars, }); const declare = declareVariable({ vars, setPath, }); const isUsed = isUsedVariable({ vars, }); const addParams = addParamsVariable(allParams); traverse(ast, getVars({ use, declare, addParams, })); allParams .map(useParamsBeforeLastUsed({ use, isUsed, })) .map(usePropertiesBeforeRest({ use, })) .map(useParamsBeforeAssign({ use, isUsed, })); return Object.values(vars); }; const addParamsVariable = (allParams) => ({path, params}) => { allParams.push({ path, params, }); }; function getScopeUID({name, scope}) { if (scope.hasOwnBinding(name)) return scope.uid; while (scope.parent) { scope = scope.parent; if (scope.hasOwnBinding(name)) return scope.uid; } return scope.uid; } const isUsedVariable = ({vars}) => (path, name) => { const {scope} = path; const uid = getScopeUID({ name, scope, }); const current = vars[uid]; const {used} = current[name]; return used; }; function getScope(path) { const {node, scope} = path; if (isFunctionDeclaration(node)) return path.parentPath.scope; if (isClassDeclaration(node)) return path.parentPath.scope; return scope; } const declareVariable = ({vars, setPath}) => (path, name) => { const scope = getScope(path); const uid = getScopeUID({ name, scope, }); if (!vars[uid]) vars[uid] = {}; const current = vars[uid]; if (current[name]) current[name].declared = true; else current[name] = { declared: true, used: false, }; if (setPath) current[name].path = path; }; const useVariable = ({vars}) => (path, name) => { const {scope} = path; const uid = getScopeUID({ name, scope, }); if (!vars[uid]) vars[uid] = {}; const current = vars[uid]; if (current[name]) current[name].used = true; else current[name] = { declared: false, used: true, }; };