Repository: eslint/eslint (js)

Issue:
space-before-function-paren removes comments when fixing
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).

    This template is for bug reports. If you are here for another reason, please see below:

    1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
    2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
    3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
    4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint

    Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->

**Tell us about your environment**

* **ESLint Version:** v6.3.0
* **Node Version:** NA (using https://eslint.org/demo)
* **npm Version:** NA (using https://eslint.org/demo)

**What parser (default, Babel-ESLint, etc.) are you using?**
default

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js
{
    "parserOptions": {
        "ecmaVersion": 10,
        "sourceType": "module",
        "ecmaFeatures": {}
    },
    "rules": {
        "space-before-function-paren": ["error", "never"]
    },
    "env": {}
}
```

</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.**

Tried to fix the following code

<!-- Paste the source code below: -->
```js
function delay /*:: <T>*/() {}
```

https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgc3BhY2UtYmVmb3JlLWZ1bmN0aW9uLXBhcmVuOiBbJ2Vycm9yJywgJ25ldmVyJ10qL1xuZnVuY3Rpb24gZGVsYXkgLyo6OiA8VD4qLygpIHt9Iiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjoxMSwic291cmNlVHlwZSI6Im1vZHVsZSIsImVjbWFGZWF0dXJlcyI6e319LCJydWxlcyI6e30sImVudiI6e319fQ==

**What did you expect to happen?**
The space after `delay` to be removed while preserving the comment.

**What actually happened? Please include the actual, raw output from ESLint.**
The space and the comment after `delay` got removed.

**Are you willing to submit a pull request to fix this bug?**
No

**Cause**
https://github.com/eslint/eslint/blob/460c5ad176eaf39ff579cd96b3bcbe0539093f8f/lib/rules/space-before-function-paren.js#L127
The fixing is done by removing everything between the identifier and the opening parenthesis (without taking comments into consideration)

Pull request description:
Fix: space-before-function-paren autofix removes comments (fixes #12259)
<!--
    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 #12259

This PR fixes the `space-before-function-paren` rule fixer with the `"never"` option, to:

* Concatenate block comments instead of removing them.
* Report error but doesn't fix anything if there is a line comment between.

Example:

[Demo link](https://eslint.org/demo#eyJ0ZXh0IjoiLyogZXNsaW50IHNwYWNlLWJlZm9yZS1mdW5jdGlvbi1wYXJlbjpbXCJlcnJvclwiLCBcIm5ldmVyXCJdKi9cblxuZnVuY3Rpb24gZm9vIC8qICovKCl7fVxuXG5mdW5jdGlvbiBiYXIgLyogMSAqL1xuLyogMiAqL1xuLyogMyAqLyAoKXt9XG5cbmZ1bmN0aW9uIGJheiAvLyBsaW5lIGNvbW1lbnRcbigpe31cblxuIiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjo1LCJzb3VyY2VUeXBlIjoic2NyaXB0IiwiZWNtYUZlYXR1cmVzIjp7fX0sInJ1bGVzIjp7ImNvbnN0cnVjdG9yLXN1cGVyIjoyLCJmb3ItZGlyZWN0aW9uIjoyLCJnZXR0ZXItcmV0dXJuIjoyLCJuby1hc3luYy1wcm9taXNlLWV4ZWN1dG9yIjoyLCJuby1jYXNlLWRlY2xhcmF0aW9ucyI6Miwibm8tY2xhc3MtYXNzaWduIjoyLCJuby1jb21wYXJlLW5lZy16ZXJvIjoyLCJuby1jb25kLWFzc2lnbiI6Miwibm8tY29uc3QtYXNzaWduIjoyLCJuby1jb25zdGFudC1jb25kaXRpb24iOjIsIm5vLWNvbnRyb2wtcmVnZXgiOjIsIm5vLWRlYnVnZ2VyIjoyLCJuby1kZWxldGUtdmFyIjoyLCJuby1kdXBlLWFyZ3MiOjIsIm5vLWR1cGUtY2xhc3MtbWVtYmVycyI6Miwibm8tZHVwZS1rZXlzIjoyLCJuby1kdXBsaWNhdGUtY2FzZSI6Miwibm8tZW1wdHkiOjIsIm5vLWVtcHR5LWNoYXJhY3Rlci1jbGFzcyI6Miwibm8tZW1wdHktcGF0dGVybiI6Miwibm8tZXgtYXNzaWduIjoyLCJuby1leHRyYS1ib29sZWFuLWNhc3QiOjIsIm5vLWV4dHJhLXNlbWkiOjIsIm5vLWZhbGx0aHJvdWdoIjoyLCJuby1mdW5jLWFzc2lnbiI6Miwibm8tZ2xvYmFsLWFzc2lnbiI6Miwibm8taW5uZXItZGVjbGFyYXRpb25zIjoyLCJuby1pbnZhbGlkLXJlZ2V4cCI6Miwibm8taXJyZWd1bGFyLXdoaXRlc3BhY2UiOjIsIm5vLW1pc2xlYWRpbmctY2hhcmFjdGVyLWNsYXNzIjoyLCJuby1taXhlZC1zcGFjZXMtYW5kLXRhYnMiOjIsIm5vLW5ldy1zeW1ib2wiOjIsIm5vLW9iai1jYWxscyI6Miwibm8tb2N0YWwiOjIsIm5vLXByb3RvdHlwZS1idWlsdGlucyI6Miwibm8tcmVkZWNsYXJlIjoyLCJuby1yZWdleC1zcGFjZXMiOjIsIm5vLXNlbGYtYXNzaWduIjoyLCJuby1zaGFkb3ctcmVzdHJpY3RlZC1uYW1lcyI6Miwibm8tc3BhcnNlLWFycmF5cyI6Miwibm8tdGhpcy1iZWZvcmUtc3VwZXIiOjIsIm5vLXVuZGVmIjoyLCJuby11bmV4cGVjdGVkLW11bHRpbGluZSI6Miwibm8tdW5yZWFjaGFibGUiOjIsIm5vLXVuc2FmZS1maW5hbGx5IjoyLCJuby11bnNhZmUtbmVnYXRpb24iOjIsIm5vLXVudXNlZC1sYWJlbHMiOjIsIm5vLXVzZWxlc3MtY2F0Y2giOjIsIm5vLXVzZWxlc3MtZXNjYXBlIjoyLCJuby13aXRoIjoyLCJyZXF1aXJlLWF0b21pYy11cGRhdGVzIjoyLCJyZXF1aXJlLXlpZWxkIjoyLCJ1c2UtaXNuYW4iOjIsInZhbGlkLXR5cGVvZiI6Mn0sImVudiI6e319fQ==)

```js
/* eslint space-before-function-paren:["error", "never"]*/

function foo /* */(){}

function bar /* 1 */
/* 2 */
/* 3 */ (){}

function baz // line comment
(){}
```

Current autofix behavior:

```js
/* eslint space-before-function-paren:["error", "never"]*/

function foo(){}

function bar(){}

function baz(){}
```

New autofix behavior:

```js
/* eslint space-before-function-paren:["error", "never"]*/

function foo/* */(){}

function bar/* 1 *//* 2 *//* 3 */(){}

function baz // line comment
(){}
```

`baz` is reported, but not auto-fixed.

<!--
    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.)
-->

<!--
    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)**

Modified the fixer to work similar to `template-tag-spacing`.

**Is there anything you'd like reviewers to focus on?**




Patch:
diff --git a/README.md b/README.md
index e51882e9c..28f512920 100644
--- a/README.md
+++ b/README.md
@@ -262,7 +262,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <!-- NOTE: This section is autogenerated. Do not manually edit.-->
 <!--sponsorsstart-->
 <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/ccd33ab/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.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/d327d66/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://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://moneypug.co.uk/"><img src="https://images.opencollective.com/moneypug/45f8d53/logo.png" alt="MONEYPUG" 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://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" 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>
 <!--sponsorsend-->
diff --git a/docs/rules/no-sequences.md b/docs/rules/no-sequences.md
index f1f4afea0..602a412f1 100644
--- a/docs/rules/no-sequences.md
+++ b/docs/rules/no-sequences.md
@@ -60,7 +60,7 @@ switch ((val = foo(), val)) {}
 
 while ((val = foo(), val < 42));
 
-// with ((doSomething(), val)) {}
+with ((doSomething(), val)) {}
 ```
 
 ## When Not To Use It
diff --git a/docs/rules/no-useless-catch.md b/docs/rules/no-useless-catch.md
index d320e561d..0562063f6 100644
--- a/docs/rules/no-useless-catch.md
+++ b/docs/rules/no-useless-catch.md
@@ -43,6 +43,12 @@ try {
 } catch (e) {
   handleError(e);
 }
+
+try {
+  doSomethingThatMightThrow();
+} finally {
+  cleanUp();
+}
 ```
 
 ## When Not To Use It
diff --git a/lib/rules/eqeqeq.js b/lib/rules/eqeqeq.js
index 58ff9030d..57926dbed 100644
--- a/lib/rules/eqeqeq.js
+++ b/lib/rules/eqeqeq.js
@@ -116,18 +116,6 @@ module.exports = {
             return astUtils.isNullLiteral(node.right) || astUtils.isNullLiteral(node.left);
         }
 
-        /**
-         * Gets the location (line and column) of the binary expression's operator
-         * @param {ASTNode} node The binary expression node to check
-         * @returns {Object} { line, column } location of operator
-         * @private
-         */
-        function getOperatorLocation(node) {
-            const opToken = sourceCode.getTokenAfter(node.left);
-
-            return { line: opToken.loc.start.line, column: opToken.loc.start.column };
-        }
-
         /**
          * Reports a message for this rule.
          * @param {ASTNode} node The binary expression node that was checked
@@ -136,21 +124,21 @@ module.exports = {
          * @private
          */
         function report(node, expectedOperator) {
+            const operatorToken = sourceCode.getFirstTokenBetween(
+                node.left,
+                node.right,
+                token => token.value === node.operator
+            );
+
             context.report({
                 node,
-                loc: getOperatorLocation(node),
+                loc: operatorToken.loc,
                 messageId: "unexpected",
                 data: { expectedOperator, actualOperator: node.operator },
                 fix(fixer) {
 
                     // If the comparison is a `typeof` comparison or both sides are literals with the same type, then it's safe to fix.
                     if (isTypeOfBinary(node) || areLiteralsAndSameType(node)) {
-                        const operatorToken = sourceCode.getFirstTokenBetween(
-                            node.left,
-                            node.right,
-                            token => token.value === node.operator
-                        );
-
                         return fixer.replaceText(operatorToken, expectedOperator);
                     }
                     return null;
diff --git a/lib/rules/no-octal-escape.js b/lib/rules/no-octal-escape.js
index a2860ca5b..7f6845ec7 100644
--- a/lib/rules/no-octal-escape.js
+++ b/lib/rules/no-octal-escape.js
@@ -20,7 +20,11 @@ module.exports = {
             url: "https://eslint.org/docs/rules/no-octal-escape"
         },
 
-        schema: []
+        schema: [],
+
+        messages: {
+            octalEscapeSequence: "Don't use octal: '\\{{sequence}}'. Use '\\u....' instead."
+        }
     },
 
     create(context) {
@@ -32,15 +36,17 @@ module.exports = {
                     return;
                 }
 
-                const match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/u);
+                // \0 represents a valid NULL character if it isn't followed by a digit.
+                const match = node.raw.match(
+                    /^(?:[^\\]|\\.)*?\\([0-3][0-7]{1,2}|[4-7][0-7]|[1-7])/u
+                );
 
                 if (match) {
-                    const octalDigit = match[2];
-
-                    // \0 is actually not considered an octal
-                    if (match[2] !== "0" || typeof match[3] !== "undefined") {
-                        context.report({ node, message: "Don't use octal: '\\{{octalDigit}}'. Use '\\u....' instead.", data: { octalDigit } });
-                    }
+                    context.report({
+                        node,
+                        messageId: "octalEscapeSequence",
+                        data: { sequence: match[1] }
+                    });
                 }
             }
 
diff --git a/lib/rules/no-unsafe-negation.js b/lib/rules/no-unsafe-negation.js
index f394f6742..717e5f6be 100644
--- a/lib/rules/no-unsafe-negation.js
+++ b/lib/rules/no-unsafe-negation.js
@@ -51,7 +51,7 @@ module.exports = {
         },
 
         schema: [],
-        fixable: "code",
+        fixable: null,
         messages: {
             unexpected: "Unexpected negating the left operand of '{{operator}}' operator."
         }
@@ -70,15 +70,7 @@ module.exports = {
                         node,
                         loc: node.left.loc,
                         messageId: "unexpected",
-                        data: { operator: node.operator },
-
-                        fix(fixer) {
-                            const negationToken = sourceCode.getFirstToken(node.left);
-                            const fixRange = [negationToken.range[1], node.range[1]];
-                            const text = sourceCode.text.slice(fixRange[0], fixRange[1]);
-
-                            return fixer.replaceTextRange(fixRange, `(${text})`);
-                        }
+                        data: { operator: node.operator }
                     });
                 }
             }
diff --git a/lib/rules/space-before-function-paren.js b/lib/rules/space-before-function-paren.js
index ca20dbc4a..3a6d430f3 100644
--- a/lib/rules/space-before-function-paren.js
+++ b/lib/rules/space-before-function-paren.js
@@ -124,7 +124,18 @@ module.exports = {
                     node,
                     loc: leftToken.loc.end,
                     message: "Unexpected space before function parentheses.",
-                    fix: fixer => fixer.removeRange([leftToken.range[1], rightToken.range[0]])
+                    fix(fixer) {
+                        const comments = sourceCode.getCommentsBefore(rightToken);
+
+                        // Don't fix anything if there's a single line comment between the left and the right token
+                        if (comments.some(comment => comment.type === "Line")) {
+                            return null;
+                        }
+                        return fixer.replaceTextRange(
+                            [leftToken.range[1], rightToken.range[0]],
+                            comments.reduce((text, comment) => text + sourceCode.getText(comment), "")
+                        );
+                    }
                 });
             } else if (!hasSpacing && functionConfig === "always") {
                 context.report({


Test patch:
diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js
index 0c6db3ff9..b3039e743 100644
--- a/tests/lib/cli-engine/cli-engine.js
+++ b/tests/lib/cli-engine/cli-engine.js
@@ -1641,6 +1641,8 @@ describe("CLIEngine", () => {
                             {
                                 column: 9,
                                 line: 2,
+                                endColumn: 11,
+                                endLine: 2,
                                 message: "Expected '===' and instead saw '=='.",
                                 messageId: "unexpected",
                                 nodeType: "BinaryExpression",
diff --git a/tests/lib/rules/eqeqeq.js b/tests/lib/rules/eqeqeq.js
index b74e9bc2c..05e33bbcf 100644
--- a/tests/lib/rules/eqeqeq.js
+++ b/tests/lib/rules/eqeqeq.js
@@ -105,6 +105,69 @@ ruleTester.run("eqeqeq", rule, {
                 { messageId: "unexpected", data: wantedNotEqEq, type: "BinaryExpression", line: 1 },
                 { messageId: "unexpected", data: wantedNotEqEq, type: "BinaryExpression", line: 1 }
             ]
+        },
+
+        // location tests
+        {
+            code: "a == b;",
+            errors: [
+                {
+                    messageId: "unexpected",
+                    data: wantedEqEqEq,
+                    type: "BinaryExpression",
+                    column: 3,
+                    endColumn: 5
+                }
+            ]
+        },
+        {
+            code: "a!=b;",
+            errors: [
+                {
+                    messageId: "unexpected",
+                    data: wantedNotEqEq,
+                    type: "BinaryExpression",
+                    column: 2,
+                    endColumn: 4
+                }
+            ]
+        },
+        {
+            code: "(a + b) == c;",
+            errors: [
+                {
+                    messageId: "unexpected",
+                    data: wantedEqEqEq,
+                    type: "BinaryExpression",
+                    column: 9,
+                    endColumn: 11
+                }
+            ]
+        },
+        {
+            code: "(a + b)  !=  c;",
+            errors: [
+                {
+                    messageId: "unexpected",
+                    data: wantedNotEqEq,
+                    type: "BinaryExpression",
+                    column: 10,
+                    endColumn: 12
+                }
+            ]
+        },
+        {
+            code: "((1) )  ==  (2);",
+            output: "((1) )  ===  (2);",
+            errors: [
+                {
+                    messageId: "unexpected",
+                    data: wantedEqEqEq,
+                    type: "BinaryExpression",
+                    column: 9,
+                    endColumn: 11
+                }
+            ]
         }
 
     // If no output is provided, assert that no output is produced.
diff --git a/tests/lib/rules/no-octal-escape.js b/tests/lib/rules/no-octal-escape.js
index b15416ebf..cd555ab60 100644
--- a/tests/lib/rules/no-octal-escape.js
+++ b/tests/lib/rules/no-octal-escape.js
@@ -24,13 +24,34 @@ ruleTester.run("no-octal-escape", rule, {
         "var foo = \"\\x51\";",
         "var foo = \"foo \\\\251 bar\";",
         "var foo = /([abc]) \\1/g;",
-        "var foo = '\\0';"
+        "var foo = '\\0';",
+        "'\\0 '",
+        "'\\0a'",
+        "'\\\\1'",
+        "'\\\\01'",
+        "'\\08'",
+        "'\\09'"
     ],
     invalid: [
+
+        // Test full message
         { code: "var foo = \"foo \\01 bar\";", errors: [{ message: "Don't use octal: '\\01'. Use '\\u....' instead.", type: "Literal" }] },
-        { code: "var foo = \"foo \\251 bar\";", errors: [{ message: "Don't use octal: '\\251'. Use '\\u....' instead.", type: "Literal" }] },
-        { code: "var foo = \"\\751\";", errors: [{ message: "Don't use octal: '\\75'. Use '\\u....' instead.", type: "Literal" }] },
-        { code: "var foo = \"\\3s51\";", errors: [{ message: "Don't use octal: '\\3'. Use '\\u....' instead.", type: "Literal" }] },
-        { code: "var foo = \"\\\\\\751\";", errors: [{ message: "Don't use octal: '\\75'. Use '\\u....' instead.", type: "Literal" }] }
+
+        { code: "var foo = \"foo \\251 bar\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "251" }, type: "Literal" }] },
+        { code: "var foo = \"\\751\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "75" }, type: "Literal" }] },
+        { code: "var foo = \"\\3s51\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "3" }, type: "Literal" }] },
+        { code: "var foo = \"\\\\\\751\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "75" }, type: "Literal" }] },
+        { code: "'\\0\\1'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "1" }, type: "Literal" }] },
+        { code: "'\\0 \\1'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "1" }, type: "Literal" }] },
+        { code: "'\\0\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] },
+        { code: "'\\0 \\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] },
+        { code: "'\\08\\1'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "1" }, type: "Literal" }] },
+        { code: "'\\08\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] },
+
+        // Only the first one is reported
+        { code: "'\\01\\02'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] },
+        { code: "'\\02\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "02" }, type: "Literal" }] },
+        { code: "'\\01\\2'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] },
+        { code: "'\\2\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "2" }, type: "Literal" }] }
     ]
 });
diff --git a/tests/lib/rules/no-unsafe-negation.js b/tests/lib/rules/no-unsafe-negation.js
index 8316aad02..6ac245412 100644
--- a/tests/lib/rules/no-unsafe-negation.js
+++ b/tests/lib/rules/no-unsafe-negation.js
@@ -34,32 +34,26 @@ ruleTester.run("no-unsafe-negation", rule, {
     invalid: [
         {
             code: "!a in b",
-            output: "!(a in b)",
             errors: [unexpectedInError]
         },
         {
             code: "(!a in b)",
-            output: "(!(a in b))",
             errors: [unexpectedInError]
         },
         {
             code: "!(a) in b",
-            output: "!((a) in b)",
             errors: [unexpectedInError]
         },
         {
             code: "!a instanceof b",
-            output: "!(a instanceof b)",
             errors: [unexpectedInstanceofError]
         },
         {
             code: "(!a instanceof b)",
-            output: "(!(a instanceof b))",
             errors: [unexpectedInstanceofError]
         },
         {
             code: "!(a) instanceof b",
-            output: "!((a) instanceof b)",
             errors: [unexpectedInstanceofError]
         }
     ]
diff --git a/tests/lib/rules/space-before-function-paren.js b/tests/lib/rules/space-before-function-paren.js
index 5bcfd7be1..961d6895a 100644
--- a/tests/lib/rules/space-before-function-paren.js
+++ b/tests/lib/rules/space-before-function-paren.js
@@ -24,6 +24,11 @@ ruleTester.run("space-before-function-paren", rule, {
         "function foo () {}",
         "var foo = function () {}",
         "var bar = function foo () {}",
+        "var bar = function foo/**/ () {}",
+        "var bar = function foo /**/() {}",
+        "var bar = function foo/**/\n() {}",
+        "var bar = function foo\n/**/() {}",
+        "var bar = function foo//\n() {}",
         "var obj = { get foo () {}, set foo (val) {} };",
         {
             code: "var obj = { foo () {} };",
@@ -34,6 +39,9 @@ ruleTester.run("space-before-function-paren", rule, {
 
         { code: "function foo() {}", options: ["never"] },
         { code: "var foo = function() {}", options: ["never"] },
+        { code: "var foo = function/**/() {}", options: ["never"] },
+        { code: "var foo = function/* */() {}", options: ["never"] },
+        { code: "var foo = function/* *//*  */() {}", options: ["never"] },
         { code: "var bar = function foo() {}", options: ["never"] },
         { code: "var obj = { get foo() {}, set foo(val) {} };", options: ["never"] },
         {
@@ -226,6 +234,84 @@ ruleTester.run("space-before-function-paren", rule, {
                 }
             ]
         },
+        {
+            code: "function foo /* */ () {}",
+            output: "function foo/* */() {}",
+            options: ["never"],
+            errors: [
+                {
+                    type: "FunctionDeclaration",
+                    message: "Unexpected space before function parentheses.",
+                    line: 1,
+                    column: 13
+                }
+            ]
+        },
+        {
+            code: "function foo/* block comment */ () {}",
+            output: "function foo/* block comment */() {}",
+            options: ["never"],
+            errors: [
+                {
+                    type: "FunctionDeclaration",
+                    message: "Unexpected space before function parentheses.",
+                    line: 1,
+                    column: 13
+                }
+            ]
+        },
+        {
+            code: "function foo/* 1 */ /* 2 */ \n /* 3 */\n/* 4 */ () {}",
+            output: "function foo/* 1 *//* 2 *//* 3 *//* 4 */() {}",
+            options: ["never"],
+            errors: [
+                {
+                    type: "FunctionDeclaration",
+                    message: "Unexpected space before function parentheses.",
+                    line: 1,
+                    column: 13
+                }
+            ]
+        },
+        {
+            code: "function foo//\n() {}",
+            output: null,
+            options: ["never"],
+            errors: [
+                {
+                    type: "FunctionDeclaration",
+                    message: "Unexpected space before function parentheses.",
+                    line: 1,
+                    column: 13
+                }
+            ]
+        },
+        {
+            code: "function foo // line comment \n () {}",
+            output: null,
+            options: ["never"],
+            errors: [
+                {
+                    type: "FunctionDeclaration",
+                    message: "Unexpected space before function parentheses.",
+                    line: 1,
+                    column: 13
+                }
+            ]
+        },
+        {
+            code: "function foo\n//\n() {}",
+            output: null,
+            options: ["never"],
+            errors: [
+                {
+                    type: "FunctionDeclaration",
+                    message: "Unexpected space before function parentheses.",
+                    line: 1,
+                    column: 13
+                }
+            ]
+        },
         {
             code: "var foo = function () {}",
             output: "var foo = function() {}",