Repository: eslint/eslint (js)

Issue:
Fixing an operator-assignment on an expression with wrapped parenthesis removes only one parenthesis
<!--
This template is for bug reports. If you are reporting a bug, please continue on. If you are here for another reason, please see below:

1. To propose a new rule: http://eslint.org/docs/developer-guide/contributing/new-rules
2. To request a change: http://eslint.org/docs/developer-guide/contributing/changes
3. 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:** 3.16.1
* **Node Version:** 6.6.0
* **npm Version:** 3.10.3

**What parser (default, Babel-ESLint, etc.) are you using?** default

**Please show your full configuration:**

<!-- Paste your configuration below: -->
```
module.exports = {
  "env": {
    "browser": true,
    "es6": true
  },
  "extends": "eslint:recommended",
  "parserOptions": {
    "sourceType": "module",
    "ecmaFeatures": {
      "experimentalObjectRestSpread": true
    }
  },
  "rules": {
    "operator-assignment": ["error", "always"],
    "no-console": "off"
  }
};
```

**What did you do? Please include the actual source code causing the issue.**

Using this code

<!-- Paste the source code below: -->
```js
let x = 0;

x = (x + 5);

console.log(x);
```

I ran ESLint's fixer.

**What did you expect to happen?**

Change `x = (x + 5);` to `x += 5`

**What actually happened? Please include the actual, raw output from ESLint.**

Changed `x = (x + 5);` to `x += 5);`

Pull request description:
Fix: `operator-assignment` with parenthesized expression (fixes #8190)
**What is the purpose of this pull request? (put an "X" next to item)**

[ ] Documentation update
[X] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

<!--
    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 (http://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)**
Correct autofix when the expression has parenthesis

**Is there anything you'd like reviewers to focus on?**
No



Patch:
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 0f505ebc7..c857caa67 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -1,7 +1,13 @@
 root: true
 
 plugins:
+    - eslint-plugin
     - node
 extends:
     - "./packages/eslint-config-eslint/default.yml"
     - "plugin:node/recommended"
+    - "plugin:eslint-plugin/recommended"
+rules:
+    eslint-plugin/consistent-output: "error"
+    eslint-plugin/prefer-placeholders: "error"
+    eslint-plugin/report-message-format: ["error", '[^a-z].*\.$']
diff --git a/lib/internal-rules/internal-no-invalid-meta.js b/lib/internal-rules/internal-no-invalid-meta.js
index d1c78efa6..d13df358b 100644
--- a/lib/internal-rules/internal-no-invalid-meta.js
+++ b/lib/internal-rules/internal-no-invalid-meta.js
@@ -94,16 +94,6 @@ function hasMetaSchema(metaPropertyNode) {
     return getPropertyFromObject("schema", metaPropertyNode.value);
 }
 
-/**
- * Whether this `meta` ObjectExpression has a `fixable` property defined or not.
- *
- * @param {ASTNode} metaPropertyNode The `meta` ObjectExpression for this rule.
- * @returns {boolean} `true` if a `fixable` property exists.
- */
-function hasMetaFixable(metaPropertyNode) {
-    return getPropertyFromObject("fixable", metaPropertyNode.value);
-}
-
 /**
  * Checks the validity of the meta definition of this rule and reports any errors found.
  *
@@ -112,7 +102,7 @@ function hasMetaFixable(metaPropertyNode) {
  * @param {boolean} ruleIsFixable whether the rule is fixable or not.
  * @returns {void}
  */
-function checkMetaValidity(context, exportsNode, ruleIsFixable) {
+function checkMetaValidity(context, exportsNode) {
     const metaProperty = getMetaPropertyFromExportsNode(exportsNode);
 
     if (!metaProperty) {
@@ -142,11 +132,6 @@ function checkMetaValidity(context, exportsNode, ruleIsFixable) {
 
     if (!hasMetaSchema(metaProperty)) {
         context.report(metaProperty, "Rule is missing a meta.schema property.");
-        return;
-    }
-
-    if (ruleIsFixable && !hasMetaFixable(metaProperty)) {
-        context.report(metaProperty, "Rule is fixable, but is missing a meta.fixable property.");
     }
 }
 
@@ -177,7 +162,6 @@ module.exports = {
 
     create(context) {
         let exportsNode;
-        let ruleIsFixable = false;
 
         return {
             AssignmentExpression(node) {
@@ -191,35 +175,13 @@ module.exports = {
                 }
             },
 
-            CallExpression(node) {
-
-                // If the rule has a call for `context.report` and a property `fix`
-                // is being passed in, then we consider that the rule is fixable.
-                //
-                // Note that we only look for context.report() calls in the new
-                // style (with single MessageDescriptor argument), because only
-                // calls in the new style can specify a fix.
-                if (node.callee.type === "MemberExpression" &&
-                    node.callee.object.type === "Identifier" &&
-                    node.callee.object.name === "context" &&
-                    node.callee.property.type === "Identifier" &&
-                    node.callee.property.name === "report" &&
-                    node.arguments.length === 1 &&
-                    node.arguments[0].type === "ObjectExpression") {
-
-                    if (getPropertyFromObject("fix", node.arguments[0])) {
-                        ruleIsFixable = true;
-                    }
-                }
-            },
-
             "Program:exit"() {
                 if (!isCorrectExportsFormat(exportsNode)) {
                     context.report({ node: exportsNode, message: "Rule does not export an Object. Make sure the rule follows the new rule format." });
                     return;
                 }
 
-                checkMetaValidity(context, exportsNode, ruleIsFixable);
+                checkMetaValidity(context, exportsNode);
             }
         };
     }
diff --git a/lib/rules/no-invalid-regexp.js b/lib/rules/no-invalid-regexp.js
index dcde234c6..45596f7ee 100644
--- a/lib/rules/no-invalid-regexp.js
+++ b/lib/rules/no-invalid-regexp.js
@@ -74,7 +74,8 @@ module.exports = {
                 } catch (e) {
                     context.report({
                         node,
-                        message: `${e.message}.`
+                        message: "{{message}}.",
+                        data: e
                     });
                 }
 
diff --git a/lib/rules/no-restricted-properties.js b/lib/rules/no-restricted-properties.js
index b6c584c57..e3a3d14e5 100644
--- a/lib/rules/no-restricted-properties.js
+++ b/lib/rules/no-restricted-properties.js
@@ -109,6 +109,7 @@ module.exports = {
             if (matchedObjectProperty) {
                 const message = matchedObjectProperty.message ? ` ${matchedObjectProperty.message}` : "";
 
+                // eslint-disable-next-line eslint-plugin/report-message-format
                 context.report({ node, message: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}", data: {
                     objectName,
                     propertyName,
@@ -117,6 +118,7 @@ module.exports = {
             } else if (globalMatchedProperty) {
                 const message = globalMatchedProperty.message ? ` ${globalMatchedProperty.message}` : "";
 
+                // eslint-disable-next-line eslint-plugin/report-message-format
                 context.report({ node, message: "'{{propertyName}}' is restricted from being used.{{message}}", data: {
                     propertyName,
                     message
diff --git a/lib/rules/no-return-await.js b/lib/rules/no-return-await.js
index 3b7324d8b..a7933460d 100644
--- a/lib/rules/no-return-await.js
+++ b/lib/rules/no-return-await.js
@@ -19,7 +19,7 @@ module.exports = {
             category: "Best Practices",
             recommended: false // TODO: set to true
         },
-        fixable: false,
+        fixable: null,
         schema: [
         ]
     },
diff --git a/lib/rules/object-shorthand.js b/lib/rules/object-shorthand.js
index 7c4275ffe..1d32d1722 100644
--- a/lib/rules/object-shorthand.js
+++ b/lib/rules/object-shorthand.js
@@ -368,11 +368,12 @@ module.exports = {
                 // Checks for property/method shorthand.
                 if (isConciseProperty) {
                     if (node.method && (APPLY_NEVER || AVOID_QUOTES && isStringLiteral(node.key))) {
+                        const message = APPLY_NEVER ? "Expected longform method syntax." : "Expected longform method syntax for string literal keys.";
 
                         // { x() {} } should be written as { x: function() {} }
                         context.report({
                             node,
-                            message: `Expected longform method syntax${APPLY_NEVER ? "" : " for string literal keys"}.`,
+                            message,
                             fix: fixer => makeFunctionLongform(fixer, node)
                         });
                     } else if (APPLY_NEVER) {
diff --git a/lib/rules/operator-assignment.js b/lib/rules/operator-assignment.js
index a6bbb177a..43f21abc8 100644
--- a/lib/rules/operator-assignment.js
+++ b/lib/rules/operator-assignment.js
@@ -135,7 +135,7 @@ module.exports = {
                                 const equalsToken = getOperatorToken(node);
                                 const operatorToken = getOperatorToken(expr);
                                 const leftText = sourceCode.getText().slice(node.range[0], equalsToken.range[0]);
-                                const rightText = sourceCode.getText().slice(operatorToken.range[1], node.range[1]);
+                                const rightText = sourceCode.getText().slice(operatorToken.range[1], expr.right.range[1]);
 
                                 return fixer.replaceText(node, `${leftText}${expr.operator}=${rightText}`);
                             }
diff --git a/lib/rules/prefer-destructuring.js b/lib/rules/prefer-destructuring.js
index 38e8e2903..d7fbc3559 100644
--- a/lib/rules/prefer-destructuring.js
+++ b/lib/rules/prefer-destructuring.js
@@ -89,7 +89,7 @@ module.exports = {
          * @returns {void}
          */
         function report(reportNode, type) {
-            context.report({ node: reportNode, message: `Use ${type} destructuring` });
+            context.report({ node: reportNode, message: "Use {{type}} destructuring.", data: { type } });
         }
 
         /**
diff --git a/lib/rules/yoda.js b/lib/rules/yoda.js
index 1a79522e7..bdb7d2a42 100644
--- a/lib/rules/yoda.js
+++ b/lib/rules/yoda.js
@@ -267,8 +267,8 @@ module.exports = {
             const operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
             const textBeforeOperator = sourceCode.getText().slice(sourceCode.getTokenBefore(operatorToken).range[1], operatorToken.range[0]);
             const textAfterOperator = sourceCode.getText().slice(operatorToken.range[1], sourceCode.getTokenAfter(operatorToken).range[0]);
-            const leftText = sourceCode.getText().slice(sourceCode.getFirstToken(node).range[0], sourceCode.getTokenBefore(operatorToken).range[1]);
-            const rightText = sourceCode.getText().slice(sourceCode.getTokenAfter(operatorToken).range[0], sourceCode.getLastToken(node).range[1]);
+            const leftText = sourceCode.getText().slice(node.range[0], sourceCode.getTokenBefore(operatorToken).range[1]);
+            const rightText = sourceCode.getText().slice(sourceCode.getTokenAfter(operatorToken).range[0], node.range[1]);
 
             return rightText + textBeforeOperator + OPERATOR_FLIP_MAP[operatorToken.value] + textAfterOperator + leftText;
         }
diff --git a/package.json b/package.json
index 72df096bc..cdd8cc0dc 100644
--- a/package.json
+++ b/package.json
@@ -81,6 +81,7 @@
     "coveralls": "^2.11.16",
     "dateformat": "^1.0.8",
     "ejs": "^2.3.3",
+    "eslint-plugin-eslint-plugin": "^0.7.1",
     "eslint-plugin-node": "^4.1.0",
     "eslint-release": "^0.10.0",
     "esprima": "^2.4.1",


Test patch:
diff --git a/tests/lib/internal-rules/internal-no-invalid-meta.js b/tests/lib/internal-rules/internal-no-invalid-meta.js
index 068e3f54a..6dd44ea2f 100644
--- a/tests/lib/internal-rules/internal-no-invalid-meta.js
+++ b/tests/lib/internal-rules/internal-no-invalid-meta.js
@@ -241,37 +241,6 @@ ruleTester.run("internal-no-invalid-meta", rule, {
                 line: 2,
                 column: 5
             }]
-        },
-        {
-            code: [
-                "module.exports = {",
-                "    meta: {",
-                "        docs: {",
-                "            description: 'some rule',",
-                "            category: 'Internal',",
-                "            recommended: false",
-                "        },",
-                "        schema: []",
-                "    },",
-                "    create: function(context) {",
-                "        return {",
-                "            Program: function(node) {",
-                "                context.report({",
-                "                    node: node,",
-                "                    fix: function(fixer) {",
-                "                        return fixer.insertTextAfter(node, ' ');",
-                "                    }",
-                "                });",
-                "            }",
-                "        };",
-                "    }",
-                "};"
-            ].join("\n"),
-            errors: [{
-                message: "Rule is fixable, but is missing a meta.fixable property.",
-                line: 2,
-                column: 5
-            }]
         }
     ]
 });
diff --git a/tests/lib/rules/brace-style.js b/tests/lib/rules/brace-style.js
index 832fe7fa8..75c86571e 100644
--- a/tests/lib/rules/brace-style.js
+++ b/tests/lib/rules/brace-style.js
@@ -479,6 +479,7 @@ ruleTester.run("brace-style", rule, {
         },
         {
             code: "try {  bar(); }\ncatch (e) { baz();  }",
+            output: "try {  bar(); }catch (e) { baz();  }",
             options: ["1tbs", { allowSingleLine: true }],
             errors: [{ message: CLOSE_MESSAGE, type: "Punctuator" }]
         },
diff --git a/tests/lib/rules/indent.js b/tests/lib/rules/indent.js
index 93378ae1b..e11d82490 100644
--- a/tests/lib/rules/indent.js
+++ b/tests/lib/rules/indent.js
@@ -2277,6 +2277,11 @@ ruleTester.run("indent", rule, {
             "    foo\n" +
             "          .bar\n" +
             "}",
+            output:
+            "var foo = function(){\n" +
+            "    foo\n" +
+            "        .bar\n" +
+            "}",
             options: [4, { MemberExpression: 1 }],
             errors: expectedErrors(
                 [3, 8, 10, "Punctuator"]
@@ -2288,6 +2293,11 @@ ruleTester.run("indent", rule, {
             "    foo\n" +
             "             .bar\n" +
             "}",
+            output:
+            "var foo = function(){\n" +
+            "    foo\n" +
+            "            .bar\n" +
+            "}",
             options: [4, { MemberExpression: 2 }],
             errors: expectedErrors(
                 [3, 12, 13, "Punctuator"]
@@ -2299,6 +2309,11 @@ ruleTester.run("indent", rule, {
             "    foo\n" +
             "             .bar\n" +
             "}",
+            output:
+            "var foo = () => {\n" +
+            "    foo\n" +
+            "            .bar\n" +
+            "}",
             options: [4, { MemberExpression: 2 }],
             parserOptions: { ecmaVersion: 6 },
             errors: expectedErrors(
@@ -2313,6 +2328,13 @@ ruleTester.run("indent", rule, {
             "        return x;\n" +
             "      });\n" +
             "};",
+            output:
+            "TestClass.prototype.method = function () {\n" +
+            "  return Promise.resolve(3)\n" +
+            "    .then(function (x) {\n" +
+            "        return x;\n" +
+            "      });\n" +
+            "};",
             options: [2, { MemberExpression: 1 }],
             parserOptions: { ecmaVersion: 6 },
             errors: expectedErrors(
@@ -3022,6 +3044,12 @@ ruleTester.run("indent", rule, {
             "    return x + 1;\n" +
             "  }\n" +
             "})();",
+            output:
+            "(function(){\n" +
+            "function foo(x) {\n" +
+            "    return x + 1;\n" +
+            "  }\n" +
+            "})();",
             options: [2, { outerIIFEBody: 0 }],
             errors: expectedErrors([[2, 0, 2, "FunctionDeclaration"]])
         },
@@ -3032,6 +3060,12 @@ ruleTester.run("indent", rule, {
             "        return x + 1;\n" +
             "    }\n" +
             "})();",
+            output:
+            "(function(){\n" +
+            "        function foo(x) {\n" +
+            "        return x + 1;\n" +
+            "    }\n" +
+            "})();",
             options: [4, { outerIIFEBody: 2 }],
             errors: expectedErrors([[2, 8, 4, "FunctionDeclaration"]])
         },
@@ -3040,6 +3074,10 @@ ruleTester.run("indent", rule, {
             "if(data) {\n" +
             "console.log('hi');\n" +
             "}",
+            output:
+            "if(data) {\n" +
+            "  console.log('hi');\n" +
+            "}",
             options: [2, { outerIIFEBody: 0 }],
             errors: expectedErrors([[2, 2, 0, "ExpressionStatement"]])
         },
@@ -3050,6 +3088,12 @@ ruleTester.run("indent", rule, {
             "        return x + 1;\n" +
             "    }\n" +
             "}(x);",
+            output:
+            "var ns = function(){\n" +
+            "        function fooVar(x) {\n" +
+            "        return x + 1;\n" +
+            "    }\n" +
+            "}(x);",
             options: [4, { outerIIFEBody: 2 }],
             errors: expectedErrors([[2, 8, 4, "FunctionDeclaration"]])
         },
@@ -3060,6 +3104,12 @@ ruleTester.run("indent", rule, {
             "  return true;\n" +
             "  }()\n" +
             "};\n",
+            output:
+            "var obj = {\n" +
+            "  foo: function() {\n" +
+            "    return true;\n" +
+            "  }()\n" +
+            "};\n",
             options: [2, { outerIIFEBody: 0 }],
             errors: expectedErrors([[3, 4, 2, "ReturnStatement"]])
         },
@@ -3070,6 +3120,12 @@ ruleTester.run("indent", rule, {
             "      return x + 1;\n" +
             "    }\n" +
             "}();",
+            output:
+            "typeof function() {\n" +
+            "  function fooVar(x) {\n" +
+            "      return x + 1;\n" +
+            "    }\n" +
+            "}();",
             options: [2, { outerIIFEBody: 2 }],
             errors: expectedErrors([[2, 2, 4, "FunctionDeclaration"]])
         },
diff --git a/tests/lib/rules/key-spacing.js b/tests/lib/rules/key-spacing.js
index 01ce0ddb1..30a9f7b1a 100644
--- a/tests/lib/rules/key-spacing.js
+++ b/tests/lib/rules/key-spacing.js
@@ -1233,6 +1233,11 @@ ruleTester.run("key-spacing", rule, {
             "          , cats: cats",
             "};"
         ].join("\n"),
+        output: [
+            "var obj = { foo : foo",
+            "          , cats: cats",
+            "};"
+        ].join("\n"),
         options: [{ align: "colon" }],
         errors: [
             { message: "Extra space after key 'foo'.", line: 1, column: 13, type: "Identifier" }
@@ -1683,6 +1688,16 @@ ruleTester.run("key-spacing", rule, {
             "    key4: 4",
             "}"
         ].join("\n"),
+        output: [
+            "var obj = {",
+            "    key1: 1,",
+            "",
+            "    key2: 2,",
+            "    key3: 3,",
+            "",
+            "    key4: 4",
+            "}"
+        ].join("\n"),
         options: [{
             multiLine: {
                 beforeColon: false,
@@ -1711,6 +1726,16 @@ ruleTester.run("key-spacing", rule, {
             "    key4: 4",
             "}"
         ].join("\n"),
+        output: [
+            "var obj = {",
+            "    key1: 1,",
+            "",
+            "    key2: 2,",
+            "    key3: 3,",
+            "",
+            "    key4: 4",
+            "}"
+        ].join("\n"),
         options: [{
             multiLine: {
                 beforeColon: false,
diff --git a/tests/lib/rules/lines-around-comment.js b/tests/lib/rules/lines-around-comment.js
index 18b1fa17d..9b2aac00e 100644
--- a/tests/lib/rules/lines-around-comment.js
+++ b/tests/lib/rules/lines-around-comment.js
@@ -1169,6 +1169,15 @@ ruleTester.run("lines-around-comment", rule, {
             "    // hi\n" +
             "  }\n" +
             "}",
+            output:
+            "function hi() {\n" +
+            "  return {\n" +
+            "    test: function() {\n" +
+            "    }\n" +
+            "    // hi\n" +
+            "\n" +
+            "  }\n" +
+            "}",
             options: [{
                 afterLineComment: true
             }],
diff --git a/tests/lib/rules/object-shorthand.js b/tests/lib/rules/object-shorthand.js
index 6d66f7cfe..8ef707d52 100644
--- a/tests/lib/rules/object-shorthand.js
+++ b/tests/lib/rules/object-shorthand.js
@@ -738,16 +738,19 @@ ruleTester.run("object-shorthand", rule, {
         // consistent
         {
             code: "var x = {a: a, b}",
+            output: null,
             options: ["consistent"],
             errors: [MIXED_SHORTHAND_ERROR]
         },
         {
             code: "var x = {b, c: d, f: g}",
+            output: null,
             options: ["consistent"],
             errors: [MIXED_SHORTHAND_ERROR]
         },
         {
             code: "var x = {foo, bar: baz, ...qux}",
+            output: null,
             parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } },
             options: ["consistent"],
             errors: [MIXED_SHORTHAND_ERROR]
@@ -756,28 +759,33 @@ ruleTester.run("object-shorthand", rule, {
         // consistent-as-needed
         {
             code: "var x = {a: a, b: b}",
+            output: null,
             options: ["consistent-as-needed"],
             errors: [ALL_SHORTHAND_ERROR]
         },
         {
             code: "var x = {a, z: function z(){}}",
+            output: null,
             options: ["consistent-as-needed"],
             errors: [MIXED_SHORTHAND_ERROR]
 
         },
         {
             code: "var x = {foo: function() {}}",
+            output: null,
             options: ["consistent-as-needed"],
             errors: [ALL_SHORTHAND_ERROR]
         },
         {
             code: "var x = {a: a, b: b, ...baz}",
+            output: null,
             parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } },
             options: ["consistent-as-needed"],
             errors: [ALL_SHORTHAND_ERROR]
         },
         {
             code: "var x = {foo, bar: bar, ...qux}",
+            output: null,
             parserOptions: { ecmaFeatures: { experimentalObjectRestSpread: true } },
             options: ["consistent-as-needed"],
             errors: [MIXED_SHORTHAND_ERROR]
diff --git a/tests/lib/rules/operator-assignment.js b/tests/lib/rules/operator-assignment.js
index d586878d7..e0f3e4e13 100644
--- a/tests/lib/rules/operator-assignment.js
+++ b/tests/lib/rules/operator-assignment.js
@@ -149,6 +149,11 @@ ruleTester.run("operator-assignment", rule, {
         output: "x += y",
         options: ["always"],
         errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x = (x + y)",
+        output: "x += y",
+        options: ["always"],
+        errors: EXPECTED_OPERATOR_ASSIGNMENT
     }, {
         code: "x += y",
         output: "x = x + y",
diff --git a/tests/lib/rules/prefer-destructuring.js b/tests/lib/rules/prefer-destructuring.js
index ae0633408..54cd76d0d 100644
--- a/tests/lib/rules/prefer-destructuring.js
+++ b/tests/lib/rules/prefer-destructuring.js
@@ -81,21 +81,21 @@ ruleTester.run("prefer-destructuring", rule, {
         {
             code: "var foo = array[0];",
             errors: [{
-                message: "Use array destructuring",
+                message: "Use array destructuring.",
                 type: "VariableDeclarator"
             }]
         },
         {
             code: "foo = array[0];",
             errors: [{
-                message: "Use array destructuring",
+                message: "Use array destructuring.",
                 type: "AssignmentExpression"
             }]
         },
         {
             code: "var foo = object.foo;",
             errors: [{
-                message: "Use object destructuring",
+                message: "Use object destructuring.",
                 type: "VariableDeclarator"
             }]
         },
@@ -103,7 +103,7 @@ ruleTester.run("prefer-destructuring", rule, {
             code: "var foobar = object.bar;",
             options: [{ object: true }, { enforceForRenamedProperties: true }],
             errors: [{
-                message: "Use object destructuring",
+                message: "Use object destructuring.",
                 type: "VariableDeclarator"
             }]
         },
@@ -111,28 +111,28 @@ ruleTester.run("prefer-destructuring", rule, {
             code: "var foo = object[bar];",
             options: [{ object: true }, { enforceForRenamedProperties: true }],
             errors: [{
-                message: "Use object destructuring",
+                message: "Use object destructuring.",
                 type: "VariableDeclarator"
             }]
         },
         {
             code: "var foo = array['foo'];",
             errors: [{
-                message: "Use object destructuring",
+                message: "Use object destructuring.",
                 type: "VariableDeclarator"
             }]
         },
         {
             code: "foo = array.foo;",
             errors: [{
-                message: "Use object destructuring",
+                message: "Use object destructuring.",
                 type: "AssignmentExpression"
             }]
         },
         {
             code: "foo = array['foo'];",
             errors: [{
-                message: "Use object destructuring",
+                message: "Use object destructuring.",
                 type: "AssignmentExpression"
             }]
         }
diff --git a/tests/lib/rules/semi.js b/tests/lib/rules/semi.js
index cf0892f86..b4653014e 100644
--- a/tests/lib/rules/semi.js
+++ b/tests/lib/rules/semi.js
@@ -140,10 +140,10 @@ ruleTester.run("semi", rule, {
         { code: "import theDefault, { named1, named2 } from 'src/mylib';", output: "import theDefault, { named1, named2 } from 'src/mylib'", options: ["never"], parserOptions: { sourceType: "module" }, errors: [{ message: "Extra semicolon.", type: "ImportDeclaration" }] },
         { code: "do{}while(true);", output: "do{}while(true)", options: ["never"], errors: [{ message: "Extra semicolon.", type: "DoWhileStatement", line: 1 }] },
 
-        { code: "if (foo) { bar()\n }", options: ["always", { omitLastInOneLineBlock: true }], errors: [{ message: "Missing semicolon." }] },
-        { code: "if (foo) {\n bar() }", options: ["always", { omitLastInOneLineBlock: true }], errors: [{ message: "Missing semicolon." }] },
-        { code: "if (foo) {\n bar(); baz() }", options: ["always", { omitLastInOneLineBlock: true }], errors: [{ message: "Missing semicolon." }] },
-        { code: "if (foo) { bar(); }", options: ["always", { omitLastInOneLineBlock: true }], errors: [{ message: "Extra semicolon." }] },
+        { code: "if (foo) { bar()\n }", output: "if (foo) { bar();\n }", options: ["always", { omitLastInOneLineBlock: true }], errors: [{ message: "Missing semicolon." }] },
+        { code: "if (foo) {\n bar() }", output: "if (foo) {\n bar(); }", options: ["always", { omitLastInOneLineBlock: true }], errors: [{ message: "Missing semicolon." }] },
+        { code: "if (foo) {\n bar(); baz() }", output: "if (foo) {\n bar(); baz(); }", options: ["always", { omitLastInOneLineBlock: true }], errors: [{ message: "Missing semicolon." }] },
+        { code: "if (foo) { bar(); }", output: "if (foo) { bar() }", options: ["always", { omitLastInOneLineBlock: true }], errors: [{ message: "Extra semicolon." }] },
 
 
         // exports, "always"
diff --git a/tests/lib/rules/sort-imports.js b/tests/lib/rules/sort-imports.js
index 19540c97f..2e08c42c3 100644
--- a/tests/lib/rules/sort-imports.js
+++ b/tests/lib/rules/sort-imports.js
@@ -136,30 +136,35 @@ ruleTester.run("sort-imports", rule, {
             code:
                 "import a from 'foo.js';\n" +
                 "import A from 'bar.js';",
+            output: null,
             errors: [expectedError]
         },
         {
             code:
                 "import b from 'foo.js';\n" +
                 "import a from 'bar.js';",
+            output: null,
             errors: [expectedError]
         },
         {
             code:
                 "import {b, c} from 'foo.js';\n" +
                 "import {a, d} from 'bar.js';",
+            output: null,
             errors: [expectedError]
         },
         {
             code:
                 "import * as foo from 'foo.js';\n" +
                 "import * as bar from 'bar.js';",
+            output: null,
             errors: [expectedError]
         },
         {
             code:
                 "import a from 'foo.js';\n" +
                 "import {b, c} from 'bar.js';",
+            output: null,
             errors: [{
                 message: "Expected 'multiple' syntax before 'single' syntax.",
                 type: "ImportDeclaration"
@@ -169,6 +174,7 @@ ruleTester.run("sort-imports", rule, {
             code:
                 "import a from 'foo.js';\n" +
                 "import * as b from 'bar.js';",
+            output: null,
             errors: [{
                 message: "Expected 'all' syntax before 'single' syntax.",
                 type: "ImportDeclaration"
@@ -178,6 +184,7 @@ ruleTester.run("sort-imports", rule, {
             code:
                 "import a from 'foo.js';\n" +
                 "import 'bar.js';",
+            output: null,
             errors: [{
                 message: "Expected 'none' syntax before 'single' syntax.",
                 type: "ImportDeclaration"
@@ -187,6 +194,7 @@ ruleTester.run("sort-imports", rule, {
             code:
                 "import b from 'bar.js';\n" +
                 "import * as a from 'foo.js';",
+            output: null,
             options: [{
                 memberSyntaxSortOrder: ["all", "single", "multiple", "none"]
             }],
diff --git a/tests/lib/rules/spaced-comment.js b/tests/lib/rules/spaced-comment.js
index 04359158d..2ee885e95 100644
--- a/tests/lib/rules/spaced-comment.js
+++ b/tests/lib/rules/spaced-comment.js
@@ -577,11 +577,13 @@ ruleTester.run("spaced-comment", rule, {
         // Parser errors
         {
             code: invalidShebangProgram,
+            output: null,
             errors: 1,
             options: ["always"]
         },
         {
             code: invalidShebangProgram,
+            output: null,
             errors: 1,
             options: ["never"]
         }
diff --git a/tests/lib/rules/strict.js b/tests/lib/rules/strict.js
index ce9191ad5..65cbbf992 100644
--- a/tests/lib/rules/strict.js
+++ b/tests/lib/rules/strict.js
@@ -92,30 +92,35 @@ ruleTester.run("strict", rule, {
         // "never" mode
         {
             code: "\"use strict\"; foo();",
+            output: null,
             options: ["never"],
             errors: [
                 { message: "Strict mode is not permitted.", type: "ExpressionStatement" }
             ]
         }, {
             code: "function foo() { 'use strict'; return; }",
+            output: null,
             options: ["never"],
             errors: [
                 { message: "Strict mode is not permitted.", type: "ExpressionStatement" }
             ]
         }, {
             code: "var foo = function() { 'use strict'; return; };",
+            output: null,
             options: ["never"],
             errors: [
                 { message: "Strict mode is not permitted.", type: "ExpressionStatement" }
             ]
         }, {
             code: "function foo() { return function() { 'use strict'; return; }; }",
+            output: null,
             options: ["never"],
             errors: [
                 { message: "Strict mode is not permitted.", type: "ExpressionStatement" }
             ]
         }, {
             code: "'use strict'; function foo() { \"use strict\"; return; }",
+            output: null,
             options: ["never"],
             errors: [
                 { message: "Strict mode is not permitted.", type: "ExpressionStatement" },
@@ -152,12 +157,14 @@ ruleTester.run("strict", rule, {
         // "global" mode
         {
             code: "foo();",
+            output: null,
             options: ["global"],
             errors: [
                 { message: "Use the global form of 'use strict'.", type: "Program" }
             ]
         }, {
             code: "function foo() { 'use strict'; return; }",
+            output: null,
             options: ["global"],
             errors: [
                 { message: "Use the global form of 'use strict'.", type: "Program" },
@@ -165,6 +172,7 @@ ruleTester.run("strict", rule, {
             ]
         }, {
             code: "var foo = function() { 'use strict'; return; }",
+            output: null,
             options: ["global"],
             errors: [
                 { message: "Use the global form of 'use strict'.", type: "Program" },
@@ -172,6 +180,7 @@ ruleTester.run("strict", rule, {
             ]
         }, {
             code: "var foo = () => { 'use strict'; return () => 1; }",
+            output: null,
             options: ["global"],
             parserOptions: { ecmaVersion: 6 },
             errors: [
@@ -180,12 +189,14 @@ ruleTester.run("strict", rule, {
             ]
         }, {
             code: "'use strict'; function foo() { 'use strict'; return; }",
+            output: null,
             options: ["global"],
             errors: [
                 { message: "Use the global form of 'use strict'.", type: "ExpressionStatement" }
             ]
         }, {
             code: "'use strict'; var foo = function() { 'use strict'; return; };",
+            output: null,
             options: ["global"],
             errors: [
                 { message: "Use the global form of 'use strict'.", type: "ExpressionStatement" }
@@ -228,12 +239,14 @@ ruleTester.run("strict", rule, {
         // "function" mode
         {
             code: "'use strict'; foo();",
+            output: null,
             options: ["function"],
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "ExpressionStatement" }
             ]
         }, {
             code: "'use strict'; (function() { 'use strict'; return true; }());",
+            output: null,
             options: ["function"],
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "ExpressionStatement" }
@@ -247,12 +260,14 @@ ruleTester.run("strict", rule, {
             ]
         }, {
             code: "(function() { return true; }());",
+            output: null,
             options: ["function"],
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "FunctionExpression" }
             ]
         }, {
             code: "(() => { return true; })();",
+            output: null,
             options: ["function"],
             parserOptions: { ecmaVersion: 6 },
             errors: [
@@ -260,6 +275,7 @@ ruleTester.run("strict", rule, {
             ]
         }, {
             code: "(() => true)();",
+            output: null,
             options: ["function"],
             parserOptions: { ecmaVersion: 6 },
             errors: [
@@ -267,6 +283,7 @@ ruleTester.run("strict", rule, {
             ]
         }, {
             code: "var foo = function() { foo(); 'use strict'; return; }; function bar() { foo(); 'use strict'; }",
+            output: null,
             options: ["function"],
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "FunctionExpression" },
@@ -314,24 +331,28 @@ ruleTester.run("strict", rule, {
             ]
         }, {
             code: "function foo() { return function() { 'use strict'; return; }; }",
+            output: null,
             options: ["function"],
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "FunctionDeclaration" }
             ]
         }, {
             code: "var foo = function() { function bar() { 'use strict'; return; } return; }",
+            output: null,
             options: ["function"],
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "FunctionExpression" }
             ]
         }, {
             code: "function foo() { 'use strict'; return; } var bar = function() { return; };",
+            output: null,
             options: ["function"],
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "FunctionExpression" }
             ]
         }, {
             code: "var foo = function() { 'use strict'; return; }; function bar() { return; };",
+            output: null,
             options: ["function"],
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "FunctionDeclaration" }
@@ -355,6 +376,7 @@ ruleTester.run("strict", rule, {
         },
         {
             code: "var foo = () => { return; };",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: ["function"],
             errors: [{ message: "Use the function form of 'use strict'.", type: "ArrowFunctionExpression" }]
@@ -387,6 +409,7 @@ ruleTester.run("strict", rule, {
         // "safe" mode corresponds to "global" if ecmaFeatures.globalReturn is true, otherwise "function"
         {
             code: "'use strict'; function foo() { return; }",
+            output: null,
             options: ["safe"],
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "ExpressionStatement" },
@@ -395,6 +418,7 @@ ruleTester.run("strict", rule, {
         },
         {
             code: "function foo() { 'use strict'; return; }",
+            output: null,
             parserOptions: { ecmaFeatures: { globalReturn: true } },
             options: ["safe"],
             errors: [
@@ -426,6 +450,7 @@ ruleTester.run("strict", rule, {
         // Default to "safe" mode
         {
             code: "'use strict'; function foo() { return; }",
+            output: null,
             errors: [
                 { message: "Use the function form of 'use strict'.", type: "ExpressionStatement" },
                 { message: "Use the function form of 'use strict'.", type: "FunctionDeclaration" }
@@ -433,10 +458,12 @@ ruleTester.run("strict", rule, {
         },
         {
             code: "function foo() { return; }",
+            output: null,
             errors: [{ message: "Use the function form of 'use strict'.", type: "FunctionDeclaration" }]
         },
         {
             code: "function foo() { 'use strict'; return; }",
+            output: null,
             parserOptions: { ecmaFeatures: { globalReturn: true } },
             errors: [
                 { message: "Use the global form of 'use strict'.", type: "Program" },
@@ -465,18 +492,21 @@ ruleTester.run("strict", rule, {
         // Reports deprecated syntax: https://github.com/eslint/eslint/issues/6405
         {
             code: "function foo(a = 0) { 'use strict' }",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: [],
             errors: ["'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016."]
         },
         {
             code: "(function() { 'use strict'; function foo(a = 0) { 'use strict' } }())",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: [],
             errors: ["'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016."]
         },
         {
             code: "function foo(a = 0) { 'use strict' }",
+            output: null,
             parserOptions: { ecmaVersion: 6, ecmaFeatures: { globalReturn: true } },
             options: [],
             errors: [
@@ -486,18 +516,21 @@ ruleTester.run("strict", rule, {
         },
         {
             code: "'use strict'; function foo(a = 0) { 'use strict' }",
+            output: null,
             parserOptions: { ecmaVersion: 6, ecmaFeatures: { globalReturn: true } },
             options: [],
             errors: ["'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016."]
         },
         {
             code: "function foo(a = 0) { 'use strict' }",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: ["never"],
             errors: ["'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016."]
         },
         {
             code: "function foo(a = 0) { 'use strict' }",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: ["global"],
             errors: [
@@ -507,30 +540,35 @@ ruleTester.run("strict", rule, {
         },
         {
             code: "'use strict'; function foo(a = 0) { 'use strict' }",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: ["global"],
             errors: ["'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016."]
         },
         {
             code: "function foo(a = 0) { 'use strict' }",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: ["function"],
             errors: ["'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016."]
         },
         {
             code: "(function() { 'use strict'; function foo(a = 0) { 'use strict' } }())",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: ["function"],
             errors: ["'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016."]
         },
         {
             code: "function foo(a = 0) { }",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: ["function"],
             errors: ["Wrap function 'foo' in a function with 'use strict' directive."]
         },
         {
             code: "(function() { function foo(a = 0) { } }())",
+            output: null,
             parserOptions: { ecmaVersion: 6 },
             options: ["function"],
             errors: ["Use the function form of 'use strict'."]