Repository: eslint/eslint (js)

Issue:
End location inference doesn't work for rules using the new-style context.report API
<!--
    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 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:** 4.3.0
* **Node Version:** 8.2.0
* **npm Version:** 5.3.0

**What parser (default, Babel-ESLint, etc.) are you using?**

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js
rules:
  no-whitespace-before-property: error
```

</details>

**What did you do? Please include the actual source code causing the issue.**

<!-- Paste the source code below: -->
```
echo 'foo .bar' | eslint --stdin --no-eslintrc --rule 'no-whitespace-before-property: error' --format json
```



**What did you expect to happen?**

I expected the resulting problem to have an `endLine` and `endColumn`, because the `no-whitespace-before-property` rule [reports a node](https://github.com/eslint/eslint/blob/2874d75ed8decf363006db25aac2d5f8991bd969/lib/rules/no-whitespace-before-property.js#L48).

**What actually happened? Please include the actual, raw output from ESLint.**

```
[{"filePath":"<text>","messages":[{"ruleId":"no-whitespace-before-property","severity":2,"message":"Unexpected whitespace before property bar.","line":1,"column":1,"nodeType":"MemberExpression","source":"foo .bar","fix":{"range":[3,5],"text":"."}}],"errorCount":1,"warningCount":0,"fixableErrorCount":1,"fixableWarningCount":0,"source":"foo .bar\n"}]
```

Note that there is no `endLine` and `endColumn`.

The issue is that the change in https://github.com/eslint/eslint/commit/b0c63f0a928cceff7cf6f060262dd7ac4bc0f8dc was incomplete. It modifies the logic in `lib/eslint.js` (which has now been renamed to `lib/linter.js`) to correctly handle the case where no location is provided. However, the report conversion logic for the object-based `context.report` API in [`rule-context.js`](https://github.com/eslint/eslint/blob/2874d75ed8decf363006db25aac2d5f8991bd969/lib/rule-context.js#L199) incorrectly passes the `start` of a node as an explicit location. The result is that `lib/linter.js` does not add an end location because it thinks an explicit start location was already provided.

The quick fix would be to replace `descriptor.node.loc.start` on [this line](https://github.com/eslint/eslint/blob/2874d75ed8decf363006db25aac2d5f8991bd969/lib/rule-context.js#L199) with `descriptor.node.loc`. As a potentially separate fix, I think we should refactor the interaction between `Linter#report` and `RuleContext#report`. This bug occurred because the two methods don't have a clear separation of responsibilities with regard to handling locations that weren't provided by the rule.

Pull request description:
Fix: refactor RuleContext to not modify report locations (fixes #8980)
<!--
    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 (https://github.com/eslint/eslint/issues/8980)

<!--
    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)**

This refactors `RuleContext` and updates it to simply pass report locations directly to `Linter`, rather than modifying them beforehand. `Linter` already contains all the necessary functionality for handling locations, so it's not necessary to duplicate any logic in `RuleContext`. The duplication caused a bug where `Linter` was modified and `RuleContext` was not.

**Is there anything you'd like reviewers to focus on?**

Nothing in particular

Patch:
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 645e328d9..7c8224968 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -10,5 +10,6 @@ extends:
 rules:
     eslint-plugin/consistent-output: "error"
     eslint-plugin/no-identical-tests: "error"
+    eslint-plugin/prefer-output-null: "error"
     eslint-plugin/prefer-placeholders: "error"
     eslint-plugin/report-message-format: ["error", '[^a-z].*\.$']
diff --git a/Makefile.js b/Makefile.js
index 3e04619d1..06cbef959 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -115,7 +115,7 @@ function validateJsonFile(filePath) {
  */
 function fileType(extension) {
     return function(filename) {
-        return filename.substring(filename.lastIndexOf(".") + 1) === extension;
+        return filename.slice(filename.lastIndexOf(".") + 1) === extension;
     };
 }
 
diff --git a/lib/config/config-file.js b/lib/config/config-file.js
index 091a24f34..34cc0d914 100644
--- a/lib/config/config-file.js
+++ b/lib/config/config-file.js
@@ -502,8 +502,8 @@ function resolve(filePath, relativeTo) {
 
     if (filePath.startsWith("plugin:")) {
         const configFullName = filePath;
-        const pluginName = filePath.substr(7, filePath.lastIndexOf("/") - 7);
-        const configName = filePath.substr(filePath.lastIndexOf("/") + 1, filePath.length - filePath.lastIndexOf("/") - 1);
+        const pluginName = filePath.slice(7, filePath.lastIndexOf("/"));
+        const configName = filePath.slice(filePath.lastIndexOf("/") + 1);
 
         normalizedPackageName = normalizePackageName(pluginName, "eslint-plugin");
         debug(`Attempting to resolve ${normalizedPackageName}`);
diff --git a/lib/config/plugins.js b/lib/config/plugins.js
index adfd8a1bb..9884f3603 100644
--- a/lib/config/plugins.js
+++ b/lib/config/plugins.js
@@ -43,7 +43,7 @@ class Plugins {
      * @returns {string} The name of the plugin without prefix.
      */
     static removePrefix(pluginName) {
-        return pluginName.startsWith(PLUGIN_NAME_PREFIX) ? pluginName.substring(PLUGIN_NAME_PREFIX.length) : pluginName;
+        return pluginName.startsWith(PLUGIN_NAME_PREFIX) ? pluginName.slice(PLUGIN_NAME_PREFIX.length) : pluginName;
     }
 
     /**
diff --git a/lib/linter.js b/lib/linter.js
index ce759756e..bb17ac216 100755
--- a/lib/linter.js
+++ b/lib/linter.js
@@ -70,8 +70,8 @@ function parseBooleanConfig(string, comment) {
         let value;
 
         if (pos !== -1) {
-            value = name.substring(pos + 1, name.length);
-            name = name.substring(0, pos);
+            value = name.slice(pos + 1);
+            name = name.slice(0, pos);
         }
 
         items[name] = {
@@ -338,7 +338,7 @@ function modifyConfigsFromComments(filename, ast, config, linterContext) {
         const match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(value);
 
         if (match) {
-            value = value.substring(match.index + match[1].length);
+            value = value.slice(match.index + match[1].length);
 
             if (comment.type === "Block") {
                 switch (match[1]) {
@@ -519,8 +519,11 @@ function createStubRule(message) {
      */
     function createRuleModule(context) {
         return {
-            Program(node) {
-                context.report(node, message);
+            Program() {
+                context.report({
+                    loc: { line: 1, column: 0 },
+                    message
+                });
             }
         };
     }
@@ -1288,13 +1291,18 @@ const externalMethods = {
 Object.keys(externalMethods).forEach(methodName => {
     const exMethodName = externalMethods[methodName];
 
-    // All functions expected to have less arguments than 5.
-    Linter.prototype[methodName] = function(a, b, c, d, e) {
-        if (this.sourceCode) {
-            return this.sourceCode[exMethodName](a, b, c, d, e);
-        }
-        return null;
-    };
+    // Applies the SourceCode methods to the Linter prototype
+    Object.defineProperty(Linter.prototype, methodName, {
+        value() {
+            if (this.sourceCode) {
+                return this.sourceCode[exMethodName].apply(this.sourceCode, arguments);
+            }
+            return null;
+        },
+        configurable: true,
+        writable: true,
+        enumerable: false
+    });
 });
 
 module.exports = Linter;
diff --git a/lib/rule-context.js b/lib/rule-context.js
index 66987b867..0a2dc188d 100644
--- a/lib/rule-context.js
+++ b/lib/rule-context.js
@@ -20,6 +20,7 @@ const PASSTHROUGHS = [
     "getDeclaredVariables",
     "getFilename",
     "getScope",
+    "getSourceCode",
     "markVariableAsUsed",
 
     // DEPRECATED
@@ -58,7 +59,7 @@ const PASSTHROUGHS = [
  */
 
 //------------------------------------------------------------------------------
-// Rule Definition
+// Module Definition
 //------------------------------------------------------------------------------
 
 /**
@@ -132,13 +133,13 @@ function getFix(descriptor, sourceCode) {
 
 /**
  * Rule context class
- * Acts as an abstraction layer between rules and the main eslint object.
+ * Acts as an abstraction layer between rules and the main linter object.
  */
 class RuleContext {
 
     /**
      * @param {string} ruleId The ID of the rule using this object.
-     * @param {eslint} eslint The eslint object.
+     * @param {Linter} linter The linter object.
      * @param {number} severity The configured severity level of the rule.
      * @param {Array} options The configuration information to be added to the rule.
      * @param {Object} settings The configuration settings passed from the config file.
@@ -147,7 +148,7 @@ class RuleContext {
      * @param {Object} meta The metadata of the rule
      * @param {Object} parserServices The parser services for the rule.
      */
-    constructor(ruleId, eslint, severity, options, settings, parserOptions, parserPath, meta, parserServices) {
+    constructor(ruleId, linter, severity, options, settings, parserOptions, parserPath, meta, parserServices) {
 
         // public.
         this.id = ruleId;
@@ -161,22 +162,14 @@ class RuleContext {
         this.parserServices = Object.freeze(Object.assign({}, parserServices));
 
         // private.
-        this.eslint = eslint;
-        this.severity = severity;
+        this._linter = linter;
+        this._severity = severity;
 
         Object.freeze(this);
     }
 
     /**
-     * Passthrough to eslint.getSourceCode().
-     * @returns {SourceCode} The SourceCode object for the code.
-     */
-    getSourceCode() {
-        return this.eslint.getSourceCode();
-    }
-
-    /**
-     * Passthrough to eslint.report() that automatically assigns the rule ID and severity.
+     * Passthrough to Linter#report() that automatically assigns the rule ID and severity.
      * @param {ASTNode|MessageDescriptor} nodeOrDescriptor The AST node related to the message or a message
      *      descriptor.
      * @param {Object=} location The location of the error.
@@ -192,38 +185,57 @@ class RuleContext {
             const descriptor = nodeOrDescriptor;
             const fix = getFix(descriptor, this.getSourceCode());
 
-            this.eslint.report(
+            if (descriptor.loc) {
+                this._linter.report(
+                    this.id,
+                    this._severity,
+                    descriptor.node,
+                    descriptor.loc,
+                    descriptor.message,
+                    descriptor.data,
+                    fix,
+                    this.meta
+                );
+            } else {
+                this._linter.report(
+                    this.id,
+                    this._severity,
+                    descriptor.node,
+
+                    /* loc not provided */
+                    descriptor.message,
+                    descriptor.data,
+                    fix,
+                    this.meta
+                );
+            }
+
+        } else {
+
+            // old style call
+            this._linter.report(
                 this.id,
-                this.severity,
-                descriptor.node,
-                descriptor.loc || descriptor.node.loc.start,
-                descriptor.message,
-                descriptor.data,
-                fix,
+                this._severity,
+                nodeOrDescriptor,
+                location,
+                message,
+                opts,
                 this.meta
             );
-
-            return;
         }
-
-        // old style call
-        this.eslint.report(
-            this.id,
-            this.severity,
-            nodeOrDescriptor,
-            location,
-            message,
-            opts,
-            this.meta
-        );
     }
 }
 
-// Copy over passthrough methods. All functions will have 5 or fewer parameters.
-PASSTHROUGHS.forEach(function(name) {
-    this[name] = function(a, b, c, d, e) {
-        return this.eslint[name](a, b, c, d, e);
-    };
-}, RuleContext.prototype);
+// Copy over passthrough methods.
+PASSTHROUGHS.forEach(name => {
+    Object.defineProperty(RuleContext.prototype, name, {
+        value() {
+            return this._linter[name].apply(this._linter, arguments);
+        },
+        configurable: true,
+        writable: true,
+        enumerable: false
+    });
+});
 
 module.exports = RuleContext;
diff --git a/lib/rules/indent-legacy.js b/lib/rules/indent-legacy.js
index f686c18ee..89d98f833 100644
--- a/lib/rules/indent-legacy.js
+++ b/lib/rules/indent-legacy.js
@@ -729,7 +729,7 @@ module.exports = {
                 if (!parentVarNode || parentVarNode.loc.start.line !== node.loc.start.line) {
                     if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) {
                         if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line === parent.loc.start.line) {
-                            nodeIndent = nodeIndent + (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]);
+                            nodeIndent += (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]);
                         } else if (parent.type === "ObjectExpression" || parent.type === "ArrayExpression") {
                             const parentElements = node.parent.type === "ObjectExpression" ? node.parent.properties : node.parent.elements;
 
@@ -765,7 +765,7 @@ module.exports = {
                         }
                     }
                 } else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && parent.type !== "MemberExpression" && parent.type !== "ExpressionStatement" && parent.type !== "AssignmentExpression" && parent.type !== "Property") {
-                    nodeIndent = nodeIndent + indentSize;
+                    nodeIndent += indentSize;
                 }
 
                 checkFirstNodeLineIndent(node, nodeIndent);
diff --git a/lib/rules/indent.js b/lib/rules/indent.js
index ec3f79170..0d4c7188b 100644
--- a/lib/rules/indent.js
+++ b/lib/rules/indent.js
@@ -1229,7 +1229,7 @@ module.exports = {
             },
 
             Property(node) {
-                if (!node.computed && !node.shorthand && !node.method && node.kind === "init") {
+                if (!node.shorthand && !node.method && node.kind === "init") {
                     const colon = sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isColonToken);
 
                     offsets.ignoreToken(sourceCode.getTokenAfter(colon));
diff --git a/lib/rules/no-multi-spaces.js b/lib/rules/no-multi-spaces.js
index 30d650c3a..fb4e017fd 100644
--- a/lib/rules/no-multi-spaces.js
+++ b/lib/rules/no-multi-spaces.js
@@ -116,7 +116,7 @@ module.exports = {
         function formatReportedCommentValue(token) {
             const valueLines = token.value.split("\n");
             const value = valueLines[0];
-            const formattedValue = `${value.substring(0, 12)}...`;
+            const formattedValue = `${value.slice(0, 12)}...`;
 
             return valueLines.length === 1 && value.length <= 12 ? value : formattedValue;
         }
diff --git a/lib/rules/space-infix-ops.js b/lib/rules/space-infix-ops.js
index ad514b28f..b92c889c7 100644
--- a/lib/rules/space-infix-ops.js
+++ b/lib/rules/space-infix-ops.js
@@ -112,7 +112,7 @@ module.exports = {
             const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode);
 
             if (nonSpacedNode) {
-                if (!(int32Hint && sourceCode.getText(node).substr(-2) === "|0")) {
+                if (!(int32Hint && sourceCode.getText(node).endsWith("|0"))) {
                     report(node, nonSpacedNode);
                 }
             }
diff --git a/package.json b/package.json
index 984592b1f..462170b0d 100644
--- a/package.json
+++ b/package.json
@@ -84,7 +84,7 @@
     "coveralls": "^2.13.1",
     "dateformat": "^2.0.0",
     "ejs": "^2.5.6",
-    "eslint-plugin-eslint-plugin": "^0.7.4",
+    "eslint-plugin-eslint-plugin": "^0.8.0",
     "eslint-plugin-node": "^5.1.0",
     "eslint-release": "^0.10.1",
     "eslump": "1.6.0",
diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml
index cdeac9ad4..f1d848ca3 100644
--- a/packages/eslint-config-eslint/default.yml
+++ b/packages/eslint-config-eslint/default.yml
@@ -10,7 +10,7 @@ rules:
     indent: ["error", 4, {SwitchCase: 1}]
     block-spacing: "error"
     brace-style: ["error", "1tbs"]
-    camelcase: ["error", { properties: "never" }]
+    camelcase: "error"
     callback-return: ["error", ["cb", "callback", "next"]]
     class-methods-use-this: "error"
     comma-dangle: "error"
@@ -20,6 +20,7 @@ rules:
     consistent-return: "error"
     curly: ["error", "all"]
     default-case: "error"
+    dot-location: ["error", "property"]
     dot-notation: ["error", { allowKeywords: true }]
     eol-last: "error"
     eqeqeq: "error"
@@ -27,7 +28,9 @@ rules:
     func-call-spacing: "error"
     func-style: ["error", "declaration"]
     generator-star-spacing: "error"
+    getter-return: "error"
     guard-for-in: "error"
+    handle-callback-err: ["error", "err"]
     key-spacing: ["error", { beforeColon: false, afterColon: true }]
     keyword-spacing: "error"
     lines-around-comment: ["error", {
@@ -41,7 +44,9 @@ rules:
     new-parens: "error"
     no-alert: "error"
     no-array-constructor: "error"
+    no-buffer-constructor: "error"
     no-caller: "error"
+    no-catch-shadow: "error"
     no-confusing-arrow: "error"
     no-console: "error"
     no-delete-var: "error"
@@ -59,6 +64,7 @@ rules:
     no-labels: "error"
     no-lone-blocks: "error"
     no-loop-func: "error"
+    no-mixed-requires: "error"
     no-mixed-spaces-and-tabs: ["error", false]
     no-multi-spaces: "error"
     no-multi-str: "error"
@@ -67,19 +73,28 @@ rules:
     no-new: "error"
     no-new-func: "error"
     no-new-object: "error"
+    no-new-require: "error"
     no-new-wrappers: "error"
     no-octal: "error"
     no-octal-escape: "error"
+    no-path-concat: "error"
     no-process-exit: "error"
     no-proto: "error"
     no-redeclare: "error"
+    no-restricted-properties: [
+        "error",
+        { property: "substring", message: "Use .slice instead of .substring." },
+        { property: "substr", message: "Use .slice instead of .substr." }
+    ]
     no-return-assign: "error"
     no-script-url: "error"
     no-self-assign: "error"
+    no-self-compare: "error"
     no-sequences: "error"
     no-shadow: "error"
     no-shadow-restricted-names: "error"
     no-tabs: "error"
+    no-throw-literal: "error"
     no-trailing-spaces: "error"
     no-undef: ["error", {typeof: true}]
     no-undef-init: "error"
@@ -90,16 +105,20 @@ rules:
     no-unused-expressions: "error"
     no-unused-vars: ["error", {vars: "all", args: "after-used"}]
     no-use-before-define: "error"
+    no-useless-call: "error"
     no-useless-computed-key: "error"
     no-useless-concat: "error"
     no-useless-constructor: "error"
     no-useless-escape: "error"
+    no-useless-rename: "error"
     no-useless-return: "error"
+    no-whitespace-before-property: "error"
     no-with: "error"
     no-var: "error"
     object-curly-spacing: ["error", "always"]
     object-shorthand: "error"
     one-var-declaration-per-line: "error"
+    operator-assignment: "error"
     operator-linebreak: "error"
     padding-line-between-statements: [
         "error",
@@ -116,6 +135,7 @@ rules:
     ]
     prefer-arrow-callback: "error"
     prefer-const: "error"
+    prefer-numeric-literals: "error"
     prefer-promise-reject-errors: "error"
     prefer-template: "error"
     quotes: ["error", "double"]
@@ -124,6 +144,7 @@ rules:
     require-jsdoc: "error"
     semi: "error"
     semi-spacing: ["error", {before: false, after: true}]
+    semi-style: "error"
     space-before-blocks: "error"
     space-before-function-paren: ["error", "never"]
     space-in-parens: "error"
@@ -131,8 +152,11 @@ rules:
     space-unary-ops: ["error", {words: true, nonwords: false}]
     spaced-comment: ["error", "always", { exceptions: ["-"]}]
     strict: ["error", "global"]
+    switch-colon-spacing: "error"
+    symbol-description: "error"
     template-curly-spacing: ["error", "never"]
     template-tag-spacing: "error"
+    unicode-bom: "error"
     valid-jsdoc: ["error", {
         prefer: { "return": "returns"},
         preferType: {
@@ -146,10 +170,3 @@ rules:
     wrap-iife: "error"
     yield-star-spacing: "error"
     yoda: ["error", "never"]
-
-    # Previously on by default in node environment
-    no-catch-shadow: "off"
-    no-mixed-requires: "error"
-    no-new-require: "error"
-    no-path-concat: "error"
-    handle-callback-err: ["error", "err"]


Test patch:
diff --git a/tests/lib/cli-engine.js b/tests/lib/cli-engine.js
index 7529d8edf..104118888 100644
--- a/tests/lib/cli-engine.js
+++ b/tests/lib/cli-engine.js
@@ -355,6 +355,8 @@ describe("CLIEngine", () => {
                                 message: "'foo' is not defined.",
                                 line: 1,
                                 column: 11,
+                                endLine: 1,
+                                endColumn: 14,
                                 nodeType: "Identifier",
                                 source: "var bar = foo"
                             }
@@ -1413,6 +1415,8 @@ describe("CLIEngine", () => {
                                 {
                                     column: 18,
                                     line: 1,
+                                    endColumn: 21,
+                                    endLine: 1,
                                     message: "'foo' is not defined.",
                                     nodeType: "Identifier",
                                     ruleId: "no-undef",
diff --git a/tests/lib/ignored-paths.js b/tests/lib/ignored-paths.js
index 1ef1f29cd..f09eab1d7 100644
--- a/tests/lib/ignored-paths.js
+++ b/tests/lib/ignored-paths.js
@@ -85,7 +85,7 @@ function countDefaultPatterns(ignoredPaths) {
     let count = ignoredPaths.defaultPatterns.length;
 
     if (!ignoredPaths.options || (ignoredPaths.options.dotfiles !== true)) {
-        count = count + 2; // Two patterns for ignoring dotfiles
+        count += 2; // Two patterns for ignoring dotfiles
     }
     return count;
 }
diff --git a/tests/lib/linter.js b/tests/lib/linter.js
index d52292abc..672088c71 100644
--- a/tests/lib/linter.js
+++ b/tests/lib/linter.js
@@ -1105,7 +1105,7 @@ describe("Linter", () => {
             assert.strictEqual(messages[0].endColumn, 2);
         });
 
-        it("should not have 'endLine' and 'endColumn' when 'loc' property doe not have 'end' property.", () => {
+        it("should not have 'endLine' and 'endColumn' when 'loc' property does not have 'end' property.", () => {
             linter.on("Program", node => {
                 linter.report(
                     "test-rule",
@@ -1122,6 +1122,13 @@ describe("Linter", () => {
             assert.strictEqual(messages[0].endColumn, void 0);
         });
 
+        it("should infer an 'endLine' and 'endColumn' property when using the object-based context.report API", () => {
+            const messages = linter.verify("foo", { rules: { "no-undef": "error" } });
+
+            assert.strictEqual(messages.length, 1);
+            assert.strictEqual(messages[0].endLine, 1);
+            assert.strictEqual(messages[0].endColumn, 4);
+        });
     });
 
     describe("when evaluating code", () => {
@@ -2697,7 +2704,19 @@ describe("Linter", () => {
 
         it("should report multiple missing rules", () => {
             assert.isArray(resultsMultiple);
-            assert.equal(resultsMultiple[1].ruleId, "barfoo");
+
+            assert.deepEqual(
+                resultsMultiple[1],
+                {
+                    ruleId: "barfoo",
+                    message: "Definition for rule 'barfoo' was not found",
+                    line: 1,
+                    column: 1,
+                    severity: 1,
+                    source: "var answer = 6 * 7;",
+                    nodeType: void 0
+                }
+            );
         });
     });
 
diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js
index 82542411c..13018bdea 100644
--- a/tests/lib/rules/getter-return.js
+++ b/tests/lib/rules/getter-return.js
@@ -51,14 +51,14 @@ ruleTester.run("getter-return", rule, {
         // option: {allowImplicit: false}
         { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});" },
         { code: "Object.defineProperty(foo, \"bar\", { get: function () { ~function (){ return true; }();return true;}});" },
-        { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });" },
-        { code: "Object.defineProperies(foo, { bar: { get: function () { ~function (){ return true; }(); return true;}} });" },
+        { code: "Object.defineProperties(foo, { bar: { get: function () {return true;}} });" },
+        { code: "Object.defineProperties(foo, { bar: { get: function () { ~function (){ return true; }(); return true;}} });" },
 
         // option: {allowImplicit: true}
         { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});", options },
         { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options },
-        { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });", options },
-        { code: "Object.defineProperies(foo, { bar: { get: function () {return;}} });", options },
+        { code: "Object.defineProperties(foo, { bar: { get: function () {return true;}} });", options },
+        { code: "Object.defineProperties(foo, { bar: { get: function () {return;}} });", options },
 
         // not getter.
         { code: "var get = function(){};" },
@@ -97,9 +97,9 @@ ruleTester.run("getter-return", rule, {
         { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", errors: [{ noReturnMessage }] },
         { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected method 'get' to always return a value." }] },
         { code: "Object.defineProperty(foo, \"bar\", { get: function (){ ~function () { return true; }()}});", errors: [{ noReturnMessage }] },
-        { code: "Object.defineProperies(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage }] },
-        { code: "Object.defineProperies(foo, { bar: { get: function (){if(bar) {return true;}}}});", options, errors: [{ message: "Expected method 'get' to always return a value." }] },
-        { code: "Object.defineProperies(foo, { bar: { get: function () {~function () { return true; }()}} });", options, errors: [{ noReturnMessage }] },
+        { code: "Object.defineProperties(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage }] },
+        { code: "Object.defineProperties(foo, { bar: { get: function (){if(bar) {return true;}}}});", options, errors: [{ message: "Expected method 'get' to always return a value." }] },
+        { code: "Object.defineProperties(foo, { bar: { get: function () {~function () { return true; }()}} });", options, errors: [{ noReturnMessage }] },
 
         // option: {allowImplicit: true}
         { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] }
diff --git a/tests/lib/rules/indent.js b/tests/lib/rules/indent.js
index fb621cb49..d1fd9c1ca 100644
--- a/tests/lib/rules/indent.js
+++ b/tests/lib/rules/indent.js
@@ -2288,6 +2288,22 @@ ruleTester.run("indent", rule, {
             `,
             options: [2]
         },
+        {
+            code: unIndent`
+                ({
+                    foo:
+                        bar
+                })
+            `
+        },
+        {
+            code: unIndent`
+                ({
+                    [foo]:
+                        bar
+                })
+            `
+        },
         {
 
             // Comments in switch cases