Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add support for removing assertion calls in SequenceExpression #42

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 118 additions & 68 deletions dist/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ function createVisitor (options) {
const targetModules = new Set(config.modules);
const targetVariables = new Set(config.variables);

const nodeUpdates = new WeakMap();

function isAssertionModuleName (lit) {
return isLiteral(lit) && targetModules.has(lit.value);
}
Expand Down Expand Up @@ -170,105 +172,153 @@ function createVisitor (options) {
return isAssertionFunction(callee) || isAssertionMethod(callee) || isConsoleAssert(callee);
}

const nodeToRemove = new WeakSet();
function removeNode (node) {
nodeUpdates.set(node, null);
}

function replaceNode (node, replacement) {
nodeUpdates.set(node, replacement);
}

function createNoopExpression () {
return {
type: 'UnaryExpression',
operator: 'void',
prefix: true,
argument: {
type: 'Literal',
value: 0,
raw: '0'
}
};
}

function createNoopStatement () {
return {
type: 'BlockStatement',
body: []
};
}

function unassertImportDeclaration (currentNode, parentNode) {
const source = currentNode.source;
if (!(isAssertionModuleName(source))) {
return;
}
// remove current ImportDeclaration
removeNode(currentNode);
this.skip();
// register local identifier(s) as assertion variable
registerAssertionVariables(currentNode);
}

function unassertVariableDeclarator (currentNode, parentNode) {
if (isRemovalTargetRequire(currentNode.id, currentNode.init)) {
if (parentNode.declarations.length === 1) {
// remove parent VariableDeclaration
removeNode(parentNode);
} else {
// single var pattern
// remove current VariableDeclarator
removeNode(currentNode);
}
this.skip();
// register local identifier(s) as assertion variable
registerAssertionVariables(currentNode.id);
}
}

function unassertAssignmentExpression (currentNode, parentNode) {
if (currentNode.operator !== '=') {
return;
}
if (!isExpressionStatement(parentNode)) {
return;
}
if (isRemovalTargetRequire(currentNode.left, currentNode.right)) {
// remove parent ExpressionStatement
removeNode(parentNode);
this.skip();
// register local identifier(s) as assertion variable
registerAssertionVariables(currentNode.left);
}
}

function unassertCallExpression (currentNode, parentNode) {
const callee = currentNode.callee;
if (!isRemovalTargetAssertion(callee)) {
return;
}

switch (parentNode.type) {
case 'ExpressionStatement': {
// remove parent ExpressionStatement
removeNode(parentNode);
this.skip();
break;
}
case 'SequenceExpression': {
// replace the asserstion with essentially nothing
replaceNode(currentNode, createNoopExpression());
break;
}
}
}

function unassertAwaitExpression (currentNode, parentNode) {
const childNode = currentNode.argument;
if (isExpressionStatement(parentNode) && isCallExpression(childNode)) {
const callee = childNode.callee;
if (isRemovalTargetAssertion(callee)) {
// remove parent ExpressionStatement
removeNode(parentNode);
this.skip();
}
}
}

return {
enter: function (currentNode, parentNode) {
switch (currentNode.type) {
case 'ImportDeclaration': {
const source = currentNode.source;
if (!(isAssertionModuleName(source))) {
return;
}
// remove current ImportDeclaration
nodeToRemove.add(currentNode);
this.skip();
// register local identifier(s) as assertion variable
registerAssertionVariables(currentNode);
unassertImportDeclaration.bind(this)(currentNode, parentNode);
break;
}
case 'VariableDeclarator': {
if (isRemovalTargetRequire(currentNode.id, currentNode.init)) {
if (parentNode.declarations.length === 1) {
// remove parent VariableDeclaration
nodeToRemove.add(parentNode);
} else {
// single var pattern
// remove current VariableDeclarator
nodeToRemove.add(currentNode);
}
this.skip();
// register local identifier(s) as assertion variable
registerAssertionVariables(currentNode.id);
}
unassertVariableDeclarator.bind(this)(currentNode, parentNode);
break;
}
case 'AssignmentExpression': {
if (currentNode.operator !== '=') {
return;
}
if (!isExpressionStatement(parentNode)) {
return;
}
if (isRemovalTargetRequire(currentNode.left, currentNode.right)) {
// remove parent ExpressionStatement
nodeToRemove.add(parentNode);
this.skip();
// register local identifier(s) as assertion variable
registerAssertionVariables(currentNode.left);
}
unassertAssignmentExpression.bind(this)(currentNode, parentNode);
break;
}
case 'CallExpression': {
if (!isExpressionStatement(parentNode)) {
return;
}
const callee = currentNode.callee;
if (isRemovalTargetAssertion(callee)) {
// remove parent ExpressionStatement
nodeToRemove.add(parentNode);
this.skip();
}
unassertCallExpression.bind(this)(currentNode, parentNode);
break;
}
case 'AwaitExpression': {
const childNode = currentNode.argument;
if (isExpressionStatement(parentNode) && isCallExpression(childNode)) {
const callee = childNode.callee;
if (isRemovalTargetAssertion(callee)) {
// remove parent ExpressionStatement
nodeToRemove.add(parentNode);
this.skip();
}
}
unassertAwaitExpression.bind(this)(currentNode, parentNode);
break;
}
}
},
leave: function (currentNode, parentNode) {
switch (currentNode.type) {
case 'ImportDeclaration':
case 'VariableDeclarator':
case 'VariableDeclaration':
case 'ExpressionStatement':
break;
default:
return undefined;
const update = nodeUpdates.get(currentNode);
if (update === undefined) {
return undefined;
}
if (nodeToRemove.has(currentNode)) {
if (update === null) {
if (isExpressionStatement(currentNode)) {
const path = this.path();
const key = path[path.length - 1];
if (isNonBlockChildOfParentNode(currentNode, parentNode, key)) {
return {
type: 'BlockStatement',
body: []
};
return createNoopStatement();
}
}
this.remove();
return undefined;
}
return undefined;
return update;
}
};
}
Expand Down
Loading