Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix: no-extra-boolean-cast invalid autofix for Boolean() without args (
…#12076)

* Fix: no-extra-boolean-cast invalid autofix for Boolean() without args

* Add test cases

* Prevent removal of comments
  • Loading branch information
mdjermanovic authored and aladdin-add committed Aug 13, 2019
1 parent 34ccc0c commit bfdb0c9
Show file tree
Hide file tree
Showing 2 changed files with 352 additions and 5 deletions.
49 changes: 44 additions & 5 deletions lib/rules/no-extra-boolean-cast.js
Expand Up @@ -50,8 +50,8 @@ module.exports = {
/**
* Check if a node is in a context where its value would be coerced to a boolean at runtime.
*
* @param {Object} node The node
* @param {Object} parent Its parent
* @param {ASTNode} node The node
* @param {ASTNode} parent Its parent
* @returns {boolean} If it is in a boolean context
*/
function isInBooleanContext(node, parent) {
Expand All @@ -65,6 +65,15 @@ module.exports = {
);
}

/**
* Check if a node has comments inside.
*
* @param {ASTNode} node The node to check.
* @returns {boolean} `true` if it has comments inside.
*/
function hasCommentsInside(node) {
return Boolean(sourceCode.getCommentsInside(node).length);
}

return {
UnaryExpression(node) {
Expand All @@ -89,7 +98,12 @@ module.exports = {
context.report({
node,
messageId: "unexpectedNegation",
fix: fixer => fixer.replaceText(parent, sourceCode.getText(node.argument))
fix: fixer => {
if (hasCommentsInside(parent)) {
return null;
}
return fixer.replaceText(parent, sourceCode.getText(node.argument));
}
});
}
},
Expand All @@ -106,10 +120,35 @@ module.exports = {
messageId: "unexpectedCall",
fix: fixer => {
if (!node.arguments.length) {
return fixer.replaceText(parent, "true");
if (parent.type === "UnaryExpression" && parent.operator === "!") {

// !Boolean() -> true

if (hasCommentsInside(parent)) {
return null;
}

const replacement = "true";
let prefix = "";
const tokenBefore = sourceCode.getTokenBefore(parent);

if (tokenBefore && tokenBefore.range[1] === parent.range[0] &&
!astUtils.canTokensBeAdjacent(tokenBefore, replacement)) {
prefix = " ";
}

return fixer.replaceText(parent, prefix + replacement);
}

// Boolean() -> false
if (hasCommentsInside(node)) {
return null;
}
return fixer.replaceText(node, "false");
}

if (node.arguments.length > 1 || node.arguments[0].type === "SpreadElement") {
if (node.arguments.length > 1 || node.arguments[0].type === "SpreadElement" ||
hasCommentsInside(node)) {
return null;
}

Expand Down
308 changes: 308 additions & 0 deletions tests/lib/rules/no-extra-boolean-cast.js
Expand Up @@ -227,6 +227,314 @@ ruleTester.run("no-extra-boolean-cast", rule, {
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "if (!Boolean()) { foo() }",
output: "if (true) { foo() }",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "while (!Boolean()) { foo() }",
output: "while (true) { foo() }",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "var foo = Boolean() ? bar() : baz()",
output: "var foo = false ? bar() : baz()",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "if (Boolean()) { foo() }",
output: "if (false) { foo() }",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "while (Boolean()) { foo() }",
output: "while (false) { foo() }",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},

// Adjacent tokens tests
{
code: "void!Boolean()",
output: "void true",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "void! Boolean()",
output: "void true",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "typeof!Boolean()",
output: "typeof true",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "(!Boolean())",
output: "(true)",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "+!Boolean()",
output: "+true",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "void !Boolean()",
output: "void true",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "void(!Boolean())",
output: "void(true)",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "void/**/!Boolean()",
output: "void/**/true",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},

// Comments tests
{
code: "!/**/!!foo",
output: "!/**/foo",
errors: [{
messageId: "unexpectedNegation",
type: "UnaryExpression"
}]
},
{
code: "!!/**/!foo",
output: null,
errors: [{
messageId: "unexpectedNegation",
type: "UnaryExpression"
}]
},
{
code: "!!!/**/foo",
output: null,
errors: [{
messageId: "unexpectedNegation",
type: "UnaryExpression"
}]
},
{
code: "!!!foo/**/",
output: "!foo/**/",
errors: [{
messageId: "unexpectedNegation",
type: "UnaryExpression"
}]
},
{
code: "if(!/**/!foo);",
output: null,
errors: [{
messageId: "unexpectedNegation",
type: "UnaryExpression"
}]
},
{
code: "(!!/**/foo ? 1 : 2)",
output: null,
errors: [{
messageId: "unexpectedNegation",
type: "UnaryExpression"
}]
},
{
code: "!/**/Boolean(foo)",
output: "!/**/foo",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "!Boolean/**/(foo)",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "!Boolean(/**/foo)",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "!Boolean(foo/**/)",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "!Boolean(foo)/**/",
output: "!foo/**/",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "if(Boolean/**/(foo));",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "(Boolean(foo/**/) ? 1 : 2)",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "/**/!Boolean()",
output: "/**/true",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "!/**/Boolean()",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "!Boolean/**/()",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "!Boolean(/**/)",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "!Boolean()/**/",
output: "true/**/",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "if(!/**/Boolean());",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "(!Boolean(/**/) ? 1 : 2)",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "if(/**/Boolean());",
output: "if(/**/false);",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "if(Boolean/**/());",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "if(Boolean(/**/));",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "if(Boolean()/**/);",
output: "if(false/**/);",
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
},
{
code: "(Boolean/**/() ? 1 : 2)",
output: null,
errors: [{
messageId: "unexpectedCall",
type: "CallExpression"
}]
}
]
});

0 comments on commit bfdb0c9

Please sign in to comment.