@putout/plugin-remove-unused-variables
Version:
🐊Putout plugin adds ability to find and remove unused variables
180 lines (142 loc) • 4.84 kB
JavaScript
import {types} from 'putout';
const {
isIdentifier,
isObjectExpression,
isObjectPattern,
isTemplateLiteral,
isAssignmentPattern,
} = types;
export const traverseObjectPattern = ({use, declare}) => {
const traverseAssign = traverseAssignmentPattern({
use,
});
return (propertiesPaths) => {
for (const path of propertiesPaths) {
if (path.isRestElement())
continue;
const {key, value} = path.node;
const valuePath = path.get('value');
switch(value.type) {
case 'Identifier':
declare(path, value.name);
break;
case 'AssignmentPattern':
if (path.node.shorthand)
declare(path, key.name);
else
declare(path, valuePath.node.left.name);
traverseAssign(valuePath);
break;
}
}
};
};
export const processObjectPattern = ({use, declare}) => (propertiesPaths) => {
for (const path of propertiesPaths) {
const {
key,
value,
computed,
} = path.node;
if (computed && isIdentifier(key))
use(path, key.name);
if (isIdentifier(value)) {
declare(path, value.name);
continue;
}
if (isObjectPattern(value)) {
const process = processObjectPattern({
use,
declare,
});
process(path.get('value.properties'));
continue;
}
if (isAssignmentPattern(value)) {
const useAssignment = traverseAssignmentPattern({
use,
});
useAssignment(path.get('value.right'));
const leftPath = path.get('value.left');
switch(leftPath.type) {
case 'Identifier':
declare(path, leftPath.node.name);
continue;
}
}
}
};
export const traverseObjectExpression = (use) => {
const traverseTmpl = traverseTemplateLiteral(use);
return (propertiesPaths) => {
for (const path of propertiesPaths) {
const {node} = path;
const {
key,
value,
computed,
} = node;
if (computed && isIdentifier(key))
use(path, key.name);
if (isIdentifier(value)) {
use(path, value.name);
continue;
}
if (isTemplateLiteral(value)) {
traverseTmpl(path, value.expressions);
continue;
}
if (isObjectExpression(value)) {
const traverseObj = traverseObjectExpression(use);
traverseObj(path.get('value.properties'));
continue;
}
}
};
};
export const traverseArrayExpression = (use) => {
const traverseObjExpression = traverseObjectExpression(use);
return (elementsPaths) => {
for (const elementPath of elementsPaths) {
const {node} = elementPath;
if (isObjectExpression(node))
traverseObjExpression(elementPath.get('properties'));
}
};
};
export const traverseAssignmentExpression = ({use, declare}) => {
const traverseObjPattern = traverseObjectPattern({
use,
declare,
});
return (path) => {
const leftPath = path.get('left');
const rightPath = path.get('right');
if (leftPath.isIdentifier()) {
const {parentPath} = leftPath.parentPath;
const {name} = leftPath.node;
if (parentPath.isObjectProperty())
declare(parentPath, name);
if (parentPath.isFunction())
declare(leftPath.parentPath, name);
}
if (rightPath.isIdentifier())
use(rightPath, rightPath.node.name);
if (leftPath.isObjectPattern())
traverseObjPattern(leftPath.get('properties'));
};
};
export const traverseTemplateLiteral = (use) => (path, expressions) => {
for (const exp of expressions) {
if (isIdentifier(exp))
use(path, exp.name);
}
};
export const traverseAssignmentPattern = ({use}) => (path) => {
const {node} = path;
const {right} = node;
if (isIdentifier(node))
use(path.parentPath, node.name);
if (isIdentifier(right))
use(path, right.name);
};