Repository: eslint/eslint (js)

Issue:
Fix range bug with no-extra-boolean-cast
**Tell us about your environment**

* **ESLint Version:** 5.12.1
* **Node Version:** 8.11.4
* **npm Version:** 5.6.0

**What parser (default, Babel-ESLint, etc.) are you using?** default

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```json
{
  "extends": ["eslint:recommended"],
  "rules": {
    "no-extra-boolean-cast": "error"
  }
}
```

</details>

**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**

<!-- Paste the source code below: -->
```js
var bar = 1;
var foo = !!bar ? 'true' : 'false';
```

<!-- Paste the command you used to run ESLint: -->
```bash
npm run lint -- --format=json
```

**What did you expect to happen?**
The information about the location of the fix appears to be off. Running `--fix` applies the fix correctly but the response from the JSON output is off (which means that other external tools cannot apply the fix).

I would expect the location information to be something like:
```json
{
  "line": 2,
  "column": 11,
  "nodeType": "UnaryExpression",
  "messageId": "unexpectedNegation",
  "endLine": 2,
  "endColumn": 16,
  "fix": { "range": [24, 29], "text": "bar" }
}
```

Looking at AST Explorer seems to have the right location information.

https://astexplorer.net/#/gist/b5517bff697af4446176699497517e36/8f1a35f7594886e63d855960a1649120071963d4
**What actually happened? Please include the actual, raw output from ESLint.**
```json
[
  {
    "filePath": "/Volumes/Freelancer/scratch/eslint/test.js",
    "messages": [
      {
        "ruleId": "no-unused-vars",
        "severity": 2,
        "message": "'foo' is assigned a value but never used.",
        "line": 2,
        "column": 5,
        "nodeType": "Identifier",
        "endLine": 2,
        "endColumn": 8
      },
      {
        "ruleId": "no-extra-boolean-cast",
        "severity": 2,
        "message": "Redundant double negation.",
        "line": 2,
        "column": 12,
        "nodeType": "UnaryExpression",
        "messageId": "unexpectedNegation",
        "endLine": 2,
        "endColumn": 16,
        "fix": { "range": [23, 28], "text": "bar" }
      }
    ],
    "errorCount": 2,
    "warningCount": 0,
    "fixableErrorCount": 1,
    "fixableWarningCount": 0,
    "source": "var bar = 1;\nvar foo = !!bar ? 'true' : 'false';\n"
  }
]
```

**Are you willing to submit a pull request to fix this bug?** With help potentially. I'm unfamiliar with how rules output the position information.


Pull request description:
Fix: no-extra-boolean-cast reports wrong negation node (fixes #11324)
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[X] Bug fix #11324

This PR fixes `no-extra-boolean-cast` to report the correct node - double negation instead of its inner negation.

Note: This PR closes #11324 as the reported `range` was not a bug.  Reported `column` was indeed a bug, and it's fixed with this PR.

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

**Tell us about your environment**

* **ESLint Version:** 6.3.0
* **Node Version:** 10.16.0
* **npm Version:** 6.9.0

**What parser (default, Babel-ESLint, etc.) are you using?**

default

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js
module.exports = {
  parserOptions: {
    ecmaVersion: 2015,
  }
};
```

</details>

**What did you do? Please include the actual source code causing the issue.**

```js
/*eslint no-extra-boolean-cast: "error"*/

!!foo ? 1 : 2
```

**What did you expect to happen?**

`3:1  error  Redundant double negation  no-extra-boolean-cast`

**What actually happened? Please include the actual, raw output from ESLint.**

`3:2  error  Redundant double negation  no-extra-boolean-cast`

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**

The rule will now report the correct node.

Autofix was already correct, this fixes just the reported location.

**Is there anything you'd like reviewers to focus on?**

Patch:
diff --git a/README.md b/README.md
index 134c991d8..d4059d374 100644
--- a/README.md
+++ b/README.md
@@ -264,7 +264,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <h3>Gold Sponsors</h3>
 <p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/d1b37c4/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/001a341/logo.png" alt="Airbnb" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
+<p><a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/docs/rules/no-irregular-whitespace.md b/docs/rules/no-irregular-whitespace.md
index a1c854d1e..a24de703a 100644
--- a/docs/rules/no-irregular-whitespace.md
+++ b/docs/rules/no-irregular-whitespace.md
@@ -168,5 +168,5 @@ If you decide that you wish to use whitespace other than tabs and spaces outside
 
 ## Further Reading
 
-* [ECMA whitespace](https://es5.github.io/#x7.2 \xA0)
+* [ECMA whitespace](https://es5.github.io/#x7.2)
 * [JSON whitespace issues](http://timelessrepo.com/json-isnt-a-javascript-subset)
diff --git a/lib/rules/no-extra-boolean-cast.js b/lib/rules/no-extra-boolean-cast.js
index 9bbd5546e..e818cd448 100644
--- a/lib/rules/no-extra-boolean-cast.js
+++ b/lib/rules/no-extra-boolean-cast.js
@@ -96,7 +96,7 @@ module.exports = {
                         grandparent.callee.name === "Boolean")
                 ) {
                     context.report({
-                        node,
+                        node: parent,
                         messageId: "unexpectedNegation",
                         fix: fixer => {
                             if (hasCommentsInside(parent)) {


Test patch:
diff --git a/tests/lib/rules/no-extra-boolean-cast.js b/tests/lib/rules/no-extra-boolean-cast.js
index 1de914ca5..a530f81f6 100644
--- a/tests/lib/rules/no-extra-boolean-cast.js
+++ b/tests/lib/rules/no-extra-boolean-cast.js
@@ -40,7 +40,9 @@ ruleTester.run("no-extra-boolean-cast", rule, {
             output: "if (foo) {}",
             errors: [{
                 messageId: "unexpectedNegation",
-                type: "UnaryExpression"
+                type: "UnaryExpression",
+                column: 5,
+                endColumn: 10
             }]
         },
         {
@@ -48,7 +50,8 @@ ruleTester.run("no-extra-boolean-cast", rule, {
             output: "do {} while (foo)",
             errors: [{
                 messageId: "unexpectedNegation",
-                type: "UnaryExpression"
+                type: "UnaryExpression",
+                column: 14
             }]
         },
         {
@@ -56,7 +59,8 @@ ruleTester.run("no-extra-boolean-cast", rule, {
             output: "while (foo) {}",
             errors: [{
                 messageId: "unexpectedNegation",
-                type: "UnaryExpression"
+                type: "UnaryExpression",
+                column: 8
             }]
         },
         {
@@ -64,7 +68,8 @@ ruleTester.run("no-extra-boolean-cast", rule, {
             output: "foo ? bar : baz",
             errors: [{
                 messageId: "unexpectedNegation",
-                type: "UnaryExpression"
+                type: "UnaryExpression",
+                column: 1
             }]
         },
         {
@@ -72,7 +77,8 @@ ruleTester.run("no-extra-boolean-cast", rule, {
             output: "for (; foo;) {}",
             errors: [{
                 messageId: "unexpectedNegation",
-                type: "UnaryExpression"
+                type: "UnaryExpression",
+                column: 8
             }]
         },
         {
@@ -80,7 +86,8 @@ ruleTester.run("no-extra-boolean-cast", rule, {
             output: "!foo",
             errors: [{
                 messageId: "unexpectedNegation",
-                type: "UnaryExpression"
+                type: "UnaryExpression",
+                column: 2
             }]
         },
         {
@@ -88,7 +95,8 @@ ruleTester.run("no-extra-boolean-cast", rule, {
             output: "Boolean(foo)",
             errors: [{
                 messageId: "unexpectedNegation",
-                type: "UnaryExpression"
+                type: "UnaryExpression",
+                column: 9
             }]
         },
         {
@@ -96,7 +104,8 @@ ruleTester.run("no-extra-boolean-cast", rule, {
             output: "new Boolean(foo)",
             errors: [{
                 messageId: "unexpectedNegation",
-                type: "UnaryExpression"
+                type: "UnaryExpression",
+                column: 13
             }]
         },
         {