Repository: eslint/eslint
Pull request #12016 (2019-07-24 05:10:50)

Docs: do not recommend global-installed usage
<!--
    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] Documentation update
[ ] 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 (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)**
do not recommend global-installed usage. this has been discussed for a long time, and seems we have done some work in this direction.

refs:
* https://github.com/eslint/eslint/issues/11914
* https://github.com/eslint/rfcs/pull/32

**Is there anything you'd like reviewers to focus on?**
seems it was not a trivial change, will it discussed in a TSC meeting?



ilyavolodin: I think it's fine to include those changes. Don't think they are controversial enough to warren TSC discussion.
aladdin-add: @kaicataldo no worries, leaving it as a draft, I just want to double-check if some more background is required. but it seems pretty clear.  😄 
aladdin-add: well, I'm going to leave it open for a longer time -- to see if there is any objections from the team, and the community.

Patch:
diff --git a/README.md b/README.md
index 18d15249f..061eafefc 100644
--- a/README.md
+++ b/README.md
@@ -59,8 +59,6 @@ After that, you can run ESLint on any file or directory like this:
 $ ./node_modules/.bin/eslint yourfile.js
 ```
 
-It is also possible to install ESLint globally rather than locally (using `npm install eslint --global`). However, any plugins or shareable configs that you use must be installed locally in either case.
-
 ## <a name="configuration"></a>Configuration
 
 After running `eslint --init`, you'll have a `.eslintrc` file in your directory. In it, you'll see some rules configured like this:
@@ -260,7 +258,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <h3>Gold Sponsors</h3>
 <p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://salesforce.com"><img src="https://images.opencollective.com/salesforce/853ecef/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/001a341/logo.png" alt="Airbnb" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a> <a href="https://faithlife.com/ref/about"><img src="https://images.opencollective.com/faithlife/534b832/logo.png" alt="Faithlife" height="32"></a></p>
+<p><a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a> <a href="https://faithlife.com/ref/about"><img src="https://images.opencollective.com/faithlife/534b832/logo.png" alt="Faithlife" height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/docs/developer-guide/nodejs-api.md b/docs/developer-guide/nodejs-api.md
index a5194004d..e6df77222 100644
--- a/docs/developer-guide/nodejs-api.md
+++ b/docs/developer-guide/nodejs-api.md
@@ -586,8 +586,9 @@ Once you have the configuration information, you can pass it into the `linter` o
 
 ```js
 const CLIEngine = require("eslint").CLIEngine,
-    linter = require("eslint").linter;
+    Linter = require("eslint").Linter;
 
+const linter = new Linter();
 const cli = new CLIEngine({
     envs: ["browser", "mocha"],
     useEslintrc: false,
diff --git a/docs/rules/func-names.md b/docs/rules/func-names.md
index cd6994006..b051d9b9b 100644
--- a/docs/rules/func-names.md
+++ b/docs/rules/func-names.md
@@ -38,6 +38,10 @@ Examples of **incorrect** code for this rule with the default `"always"` option:
 
 Foo.prototype.bar = function() {};
 
+const cat = {
+  meow: function() {}
+}
+
 (function() {
     // ...
 }())
@@ -50,6 +54,10 @@ Examples of **correct** code for this rule with the default `"always"` option:
 
 Foo.prototype.bar = function bar() {};
 
+const cat = {
+  meow() {}
+}
+
 (function bar() {
     // ...
 }())
@@ -78,6 +86,10 @@ Examples of **correct** code for this rule with the `"as-needed"` option:
 
 var bar = function() {};
 
+const cat = {
+  meow: function() {}
+}
+
 (function bar() {
     // ...
 }())
diff --git a/docs/rules/no-restricted-globals.md b/docs/rules/no-restricted-globals.md
index e3d612412..dd3e15b7b 100644
--- a/docs/rules/no-restricted-globals.md
+++ b/docs/rules/no-restricted-globals.md
@@ -77,7 +77,7 @@ Examples of **incorrect** code for a sample `"event"` global variable name, alon
 
 ```js
 /*global event*/
-/* eslint no-restricted-globals: ["error", { name: "error", message: "Use local parameter instead." }] */
+/* eslint no-restricted-globals: ["error", { name: "event", message: "Use local parameter instead." }] */
 
 function onClick() {
     console.log(event);    // Unexpected global variable 'event'. Use local parameter instead.
diff --git a/docs/rules/no-undef.md b/docs/rules/no-undef.md
index f5dc5a280..faaf978cc 100644
--- a/docs/rules/no-undef.md
+++ b/docs/rules/no-undef.md
@@ -11,32 +11,25 @@ Examples of **incorrect** code for this rule:
 ```js
 /*eslint no-undef: "error"*/
 
-var a = someFunction();
-b = 10;
+var foo = someFunction();
+var bar = a + 1;
 ```
 
 Examples of **correct** code for this rule with `global` declaration:
 
 ```js
-/*global someFunction b:writable*/
+/*global someFunction, a*/
 /*eslint no-undef: "error"*/
 
-var a = someFunction();
-b = 10;
+var foo = someFunction();
+var bar = a + 1;
 ```
 
-The `b:writable` syntax in `/*global */` indicates that assignment to `b` is correct.
+Note that this rule does not disallow assignments to read-only global variables.
+See [no-global-assign](no-global-assign.md) if you also want to disallow those assignments.
 
-Examples of **incorrect** code for this rule with `global` declaration:
-
-```js
-/*global b*/
-/*eslint no-undef: "error"*/
-
-b = 10;
-```
-
-By default, variables declared in `/*global */` are read-only, therefore assignment is incorrect.
+This rule also does not disallow redeclarations of global variables.
+See [no-redeclare](no-redeclare.md) if you also want to disallow those redeclarations.
 
 ## Options
 
@@ -111,3 +104,8 @@ If explicit declaration of global variables is not to your taste.
 ## Compatibility
 
 This rule provides compatibility with treatment of global variables in [JSHint](http://jshint.com/) and [JSLint](http://www.jslint.com).
+
+## Related Rules
+
+* [no-global-assign](no-global-assign.md)
+* [no-redeclare](no-redeclare.md)
diff --git a/docs/user-guide/getting-started.md b/docs/user-guide/getting-started.md
index 45633f618..1bebf7d69 100644
--- a/docs/user-guide/getting-started.md
+++ b/docs/user-guide/getting-started.md
@@ -33,7 +33,7 @@ After that, you can run ESLint on any file or directory like this:
 $ ./node_modules/.bin/eslint yourfile.js
 ```
 
-It is also possible to install ESLint globally rather than locally (using `npm install eslint --global`). However, any plugins or shareable configs that you use must be installed locally in either case.
+It is also possible to install ESLint globally rather than locally (using `npm install eslint --global`). However, this is not recommended, and any plugins or shareable configs that you use must be installed locally in either case.
 
 ## Configuration
 
diff --git a/lib/rules/class-methods-use-this.js b/lib/rules/class-methods-use-this.js
index 0eb1da87f..c15f32e66 100644
--- a/lib/rules/class-methods-use-this.js
+++ b/lib/rules/class-methods-use-this.js
@@ -70,7 +70,8 @@ module.exports = {
          * @private
          */
         function isIncludedInstanceMethod(node) {
-            return isInstanceMethod(node) && !exceptMethods.has(node.key.name);
+            return isInstanceMethod(node) &&
+                (node.computed || !exceptMethods.has(node.key.name));
         }
 
         /**
diff --git a/lib/rules/func-names.js b/lib/rules/func-names.js
index 01beb9e2e..ff3a1f4b5 100644
--- a/lib/rules/func-names.js
+++ b/lib/rules/func-names.js
@@ -69,6 +69,8 @@ module.exports = {
 
     create(context) {
 
+        const sourceCode = context.getSourceCode();
+
         /**
          * Returns the config option for the given node.
          * @param {ASTNode} node - A node to get the config for.
@@ -130,6 +132,7 @@ module.exports = {
             context.report({
                 node,
                 messageId: "unnamed",
+                loc: astUtils.getFunctionHeadLoc(node, sourceCode),
                 data: { name: astUtils.getFunctionNameWithKind(node) }
             });
         }
@@ -143,6 +146,7 @@ module.exports = {
             context.report({
                 node,
                 messageId: "named",
+                loc: astUtils.getFunctionHeadLoc(node, sourceCode),
                 data: { name: astUtils.getFunctionNameWithKind(node) }
             });
         }
diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js
index 6c3198b5f..c9278f2d0 100644
--- a/lib/rules/no-extra-parens.js
+++ b/lib/rules/no-extra-parens.js
@@ -686,6 +686,13 @@ module.exports = {
 
             CallExpression: checkCallNew,
 
+            ClassBody(node) {
+                node.body
+                    .filter(member => member.type === "MethodDefinition" && member.computed &&
+                        member.key && hasExcessParens(member.key) && precedence(member.key) >= PRECEDENCE_OF_ASSIGNMENT_EXPR)
+                    .forEach(member => report(member.key));
+            },
+
             ConditionalExpression(node) {
                 if (isReturnAssignException(node)) {
                     return;
diff --git a/lib/rules/no-restricted-syntax.js b/lib/rules/no-restricted-syntax.js
index 74eea1478..41aa9fa39 100644
--- a/lib/rules/no-restricted-syntax.js
+++ b/lib/rules/no-restricted-syntax.js
@@ -21,7 +21,7 @@ module.exports = {
 
         schema: {
             type: "array",
-            items: [{
+            items: {
                 oneOf: [
                     {
                         type: "string"
@@ -36,7 +36,7 @@ module.exports = {
                         additionalProperties: false
                     }
                 ]
-            }],
+            },
             uniqueItems: true,
             minItems: 0
         }


Test patch:
diff --git a/tests/lib/rules/class-methods-use-this.js b/tests/lib/rules/class-methods-use-this.js
index 852124245..89af434fd 100644
--- a/tests/lib/rules/class-methods-use-this.js
+++ b/tests/lib/rules/class-methods-use-this.js
@@ -97,6 +97,14 @@ ruleTester.run("class-methods-use-this", rule, {
             errors: [
                 { type: "FunctionExpression", line: 1, column: 34, messageId: "missingThis", data: { name: "hasOwnProperty" } }
             ]
+        },
+        {
+            code: "class A { [foo]() {} }",
+            options: [{ exceptMethods: ["foo"] }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { type: "FunctionExpression", line: 1, column: 16, messageId: "missingThis", data: { name: "foo" } }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/func-names.js b/tests/lib/rules/func-names.js
index 3fcfc50a3..1976d565c 100644
--- a/tests/lib/rules/func-names.js
+++ b/tests/lib/rules/func-names.js
@@ -17,7 +17,6 @@ const rule = require("../../../lib/rules/func-names"),
 //------------------------------------------------------------------------------
 
 const ruleTester = new RuleTester();
-const unnamedError = { messageId: "unnamed", type: "FunctionExpression" };
 
 ruleTester.run("func-names", rule, {
     valid: [
@@ -254,73 +253,166 @@ ruleTester.run("func-names", rule, {
     invalid: [
         {
             code: "Foo.prototype.bar = function() {};",
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 21,
+                endColumn: 29
+            }]
         },
         {
             code: "(function(){}())",
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 10
+            }]
         },
         {
             code: "f(function(){})",
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 3,
+                endColumn: 11
+            }]
         },
         {
             code: "var a = new Date(function() {});",
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 18,
+                endColumn: 26
+            }]
         },
         {
             code: "var test = function(d, e, f) {};",
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 12,
+                endColumn: 20
+            }]
         },
         {
             code: "new function() {}",
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 5,
+                endColumn: 13
+            }]
         },
         {
             code: "Foo.prototype.bar = function() {};",
             options: ["as-needed"],
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 21,
+                endColumn: 29
+            }]
         },
         {
             code: "(function(){}())",
             options: ["as-needed"],
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 10
+            }]
         },
         {
             code: "f(function(){})",
             options: ["as-needed"],
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 3,
+                endColumn: 11
+            }]
         },
         {
             code: "var a = new Date(function() {});",
             options: ["as-needed"],
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 18,
+                endColumn: 26
+            }]
         },
         {
             code: "new function() {}",
             options: ["as-needed"],
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 5,
+                endColumn: 13
+            }]
         },
         {
             code: "var {foo} = function(){};",
             options: ["as-needed"],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 13,
+                endColumn: 21
+            }]
         },
         {
             code: "var x = function foo() {};",
             options: ["never"],
-            errors: [{ messageId: "named", data: { name: "function 'foo'" }, type: "FunctionExpression" }]
+            errors: [{
+                messageId: "named",
+                data: { name: "function 'foo'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 9,
+                endColumn: 21
+            }]
         },
         {
             code: "Foo.prototype.bar = function foo() {};",
             options: ["never"],
-            errors: [{ messageId: "named", data: { name: "function 'foo'" }, type: "FunctionExpression" }]
+            errors: [{
+                messageId: "named",
+                data: { name: "function 'foo'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 21,
+                endColumn: 33
+            }]
         },
         {
             code: "({foo: function foo() {}})",
             options: ["never"],
-            errors: [{ messageId: "named", data: { name: "method 'foo'" }, type: "FunctionExpression" }]
+            errors: [{
+                messageId: "named",
+                data: { name: "method 'foo'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 3,
+                endColumn: 20
+            }]
         },
 
         // generators
@@ -328,121 +420,241 @@ ruleTester.run("func-names", rule, {
             code: "var foo = bar(function *() {});",
             options: ["always"],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 25
+            }]
         },
         {
             code: "var foo = function*() {};",
             options: ["always"],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 11,
+                endColumn: 20
+            }]
         },
         {
             code: "(function*() {}())",
             options: ["always"],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 11
+            }]
         },
         {
             code: "var foo = bar(function *() {});",
             options: ["always", { generators: "always" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 25
+            }]
         },
         {
             code: "var foo = function*() {};",
             options: ["always", { generators: "always" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 11,
+                endColumn: 20
+            }]
         },
         {
             code: "(function*() {}())",
             options: ["always", { generators: "always" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 11
+            }]
         },
         {
             code: "var foo = bar(function *() {});",
             options: ["always", { generators: "as-needed" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 25
+            }]
         },
         {
             code: "(function*() {}())",
             options: ["always", { generators: "as-needed" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 11
+            }]
         },
         {
             code: "var foo = bar(function *() {});",
             options: ["as-needed"],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 25
+            }]
         },
         {
             code: "(function*() {}())",
             options: ["as-needed"],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 11
+            }]
         },
         {
             code: "var foo = bar(function *() {});",
             options: ["as-needed", { generators: "always" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 25
+            }]
         },
         {
             code: "var foo = function*() {};",
             options: ["as-needed", { generators: "always" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 11,
+                endColumn: 20
+            }]
         },
         {
             code: "(function*() {}())",
             options: ["as-needed", { generators: "always" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 11
+            }]
         },
         {
             code: "var foo = bar(function *() {});",
             options: ["as-needed", { generators: "as-needed" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 25
+            }]
         },
         {
             code: "(function*() {}())",
             options: ["as-needed", { generators: "as-needed" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 11
+            }]
         },
         {
             code: "var foo = bar(function *() {});",
             options: ["never", { generators: "always" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 25
+            }]
         },
         {
             code: "var foo = function*() {};",
             options: ["never", { generators: "always" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 11,
+                endColumn: 20
+            }]
         },
         {
             code: "(function*() {}())",
             options: ["never", { generators: "always" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 11
+            }]
         },
         {
             code: "var foo = bar(function *() {});",
             options: ["never", { generators: "as-needed" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 25
+            }]
         },
         {
             code: "(function*() {}())",
             options: ["never", { generators: "as-needed" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [unnamedError]
+            errors: [{
+                messageId: "unnamed",
+                type: "FunctionExpression",
+                line: 1,
+                column: 2,
+                endColumn: 11
+            }]
         },
 
         {
@@ -450,26 +662,52 @@ ruleTester.run("func-names", rule, {
             options: ["never"],
             parserOptions: { ecmaVersion: 6 },
             errors: [{
-                message: "Unexpected named generator function 'baz'."
+                messageId: "named",
+                data: { name: "generator function 'baz'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 28
             }]
         },
         {
             code: "var foo = bar(function *baz() {});",
             options: ["never", { generators: "never" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "named", data: { name: "generator function 'baz'" }, type: "FunctionExpression" }]
+            errors: [{
+                messageId: "named",
+                data: { name: "generator function 'baz'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 28
+            }]
         },
         {
             code: "var foo = bar(function *baz() {});",
             options: ["always", { generators: "never" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "named", data: { name: "generator function 'baz'" }, type: "FunctionExpression" }]
+            errors: [{
+                messageId: "named",
+                data: { name: "generator function 'baz'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 28
+            }]
         },
         {
             code: "var foo = bar(function *baz() {});",
             options: ["as-needed", { generators: "never" }],
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ messageId: "named", data: { name: "generator function 'baz'" }, type: "FunctionExpression" }]
+            errors: [{
+                messageId: "named",
+                data: { name: "generator function 'baz'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 15,
+                endColumn: 28
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js
index 7be7d6e9e..6c6eeb2a1 100644
--- a/tests/lib/rules/no-extra-parens.js
+++ b/tests/lib/rules/no-extra-parens.js
@@ -160,6 +160,13 @@ ruleTester.run("no-extra-parens", rule, {
         "const {[a]:b=1} = {}",
         "const {[(a, b)]:c} = {}",
         "const {a, ...b} = {}",
+        "class foo {}",
+        "class foo { constructor(){} a(){} get b(){} set b(bar){} get c(){} set d(baz){} static e(){} }",
+        "class foo { [a](){} get [b](){} set [b](bar){} get [c](){} set [d](baz){} static [e](){} }",
+        "class foo { [(a,b)](){} }",
+        "class foo { a(){} [b](){} c(){} [(d,e)](){} }",
+        "class foo { [(a,b)](){} c(){} [d](){} e(){} }",
+        "const foo = class { constructor(){} a(){} get b(){} set b(bar){} get c(){} set d(baz){} static e(){} }",
 
         // ExpressionStatement restricted productions
         "({});",
@@ -553,6 +560,22 @@ ruleTester.run("no-extra-parens", rule, {
         invalid("const {a, b:c, [(d+e)]:f, [(g,h)]:i, [j]:k} = {}", "const {a, b:c, [d+e]:f, [(g,h)]:i, [j]:k} = {}", "BinaryExpression", 1),
         invalid("const {[a+(b*c)]:d} = {}", "const {[a+b*c]:d} = {}", "BinaryExpression", 1),
         invalid("const {[(a, (b+c))]:d} = {}", "const {[(a, b+c)]:d} = {}", "BinaryExpression", 1),
+        invalid("class foo { [(a)](){} }", "class foo { [a](){} }", "Identifier"),
+        invalid("class foo {*[(Symbol.iterator)]() {}}", "class foo {*[Symbol.iterator]() {}}", "MemberExpression"),
+        invalid("class foo { get [(a)](){} }", "class foo { get [a](){} }", "Identifier"),
+        invalid("class foo { set [(a)](bar){} }", "class foo { set [a](bar){} }", "Identifier"),
+        invalid("class foo { static [(a)](bar){} }", "class foo { static [a](bar){} }", "Identifier"),
+        invalid("class foo { [(a=b)](){} }", "class foo { [a=b](){} }", "AssignmentExpression"),
+        invalid("class foo { constructor (){} [(a+b)](){} }", "class foo { constructor (){} [a+b](){} }", "BinaryExpression"),
+        invalid("class foo { [(a+b)](){} constructor (){} }", "class foo { [a+b](){} constructor (){} }", "BinaryExpression"),
+        invalid("class foo { [(a+b)](){} c(){} }", "class foo { [a+b](){} c(){} }", "BinaryExpression"),
+        invalid("class foo { a(){} [(b+c)](){} d(){} }", "class foo { a(){} [b+c](){} d(){} }", "BinaryExpression"),
+        invalid("class foo { [(a+b)](){} [c](){} }", "class foo { [a+b](){} [c](){} }", "BinaryExpression"),
+        invalid("class foo { [a](){} [(b+c)](){} [d](){} }", "class foo { [a](){} [b+c](){} [d](){} }", "BinaryExpression"),
+        invalid("class foo { [(a+b)](){} [(c,d)](){} }", "class foo { [a+b](){} [(c,d)](){} }", "BinaryExpression"),
+        invalid("class foo { [(a,b)](){} [(c+d)](){} }", "class foo { [(a,b)](){} [c+d](){} }", "BinaryExpression"),
+        invalid("class foo { [a+(b*c)](){} }", "class foo { [a+b*c](){} }", "BinaryExpression"),
+        invalid("const foo = class { [(a)](){} }", "const foo = class { [a](){} }", "Identifier"),
         invalid(
             "var foo = (function*() { if ((yield foo())) { return; } }())",
             "var foo = (function*() { if (yield foo()) { return; } }())",