question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Missing parentheses around LogicalExpression inside of UnaryExpression

See original GitHub issue

I believe I’ve stumbled onto a bug in jscodeshift: I created a transform to convert

(a && b) || c();

to

if (!(a && b)) {
  c();
}

However, when I wrap the initial LogicalExpression in a ! UnaryExpression, jscodeshift instead outputs:

if (!a && b) {
  c();
}

which has a different meaning due to the missing parentheses.

The issue on AST explorer: https://astexplorer.net/#/gist/4f8d333d868a270bd53098d4f283e8fa/5cb2224e8c7cbc178130c3da2ab6683e4a1064bc

Output of jscodeshift --version:

jscodeshift: 0.11.0
 - babel: 7.13.14
 - babylon: 7.13.13
 - flow: 0.148.0
 - recast: 0.20.4

I don’t believe this is an issue with recast, because I wrote some code that does the same thing purely using recast, and it works:

var recast = require("recast");
const b = recast.types.builders;

const code = [
  "(a && b) || c();"
].join("\n");

const ast = recast.parse(code);
const expression = ast.program.body[0].expression;
const body = b.blockStatement([b.expressionStatement(expression.right)]);
const cond = b.unaryExpression("!", expression.left);
const ifStatement = b.ifStatement(cond, body, null);
ast.program.body[0] = ifStatement;
const output = recast.print(ast).code;

console.log(output);

outputs:

if (!(a && b)) {
  c();
}

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
fcsonlinecommented, Dec 11, 2021

Thanks for the information @mobily !!. Do you have a link to the documentation related to this?

1reaction
mobilycommented, Dec 11, 2021

@fcsonline I think what you need is adding node.left.prefix = true

https://astexplorer.net/#/gist/4f8d333d868a270bd53098d4f283e8fa/b2b9239fb3c2281723659f4d55a8efb944919d51

export default function transformer(file, api) {
  const j = api.jscodeshift;
  var program = j(file.source);

  program
    .find(j.ExpressionStatement, {
      expression: {
        type: "LogicalExpression",
      },
    })
    .replaceWith((p) => {
      var node = p.node.expression;
      if (node.operator == "||") {
        node.left.prefix = true
        var expr = j.unaryExpression("!", node.left, true);
        var then = j.blockStatement([j.expressionStatement(node.right)]);
        return j.ifStatement(expr, then, null);
      } else {
        return p;
      }
    });

  return program.toSource();
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Purpose of parentheses around expressions joined by logical ...
In this case, the order of operations makes the two statements (and return a != null && b != null , without any...
Read more >
Logical OR (||) - JavaScript - MDN Web Docs - Mozilla
As logical expressions are evaluated left to right, it is always possible to remove parentheses from a complex expression following some rules.
Read more >
Dafny Reference Manual
Many of the types, functions, and methods in Dafny can be parameterized by types. These type parameters are typically declared inside angle brackets...
Read more >
prettierx | Yarn - Package Manager
... extra parenthesis around await inside of unary expression (#745); Fix missing ... Remove unneeded parens for FunctionExpression inside LogicalExpression ...
Read more >
State of the Art Expression Evaluation - CodeProject
In any logical expression, mathematical functions are used whether ... It is made of optional opening and closing parentheses containing ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found