Repository: jshint/jshint (JavaScript)

Issue:
2.10.0 marks variables as unused when they are not
I have a file that looks like this

```js

import {foo} from './foo';

class MyClass {
  foo(){
     return foo();
  }
}
```

and it is incorrectly marking foo as unused. This is a valid use since the call to `foo` is not referring to `this.foo` so it must be the imported `foo`


Discussion:
Confirmed. Thanks for the report!
Introduced via 6759ac902928c32e0c798134abe1fbd1353ad3a3
Further reduced:

    // jshint esversion: 6
    var m;
    class C {
      m() {
        void m;
      }
    }

This effects:

- methods
- static methods
- accessor methods
- genereate methods
- async methods
- async generator methods

This does *not* effect constructor methods, e.g.

    // jshint esversion: 6
    var constructor;
    class C {
      constructor() {
        void constructor;
      }
    }


Fix on the way: gh-3355
[Released in JSHint 2.10.1](https://jshint.com/blog/2019-02-05/release-2-10-1)



Patch:
diff --git a/src/jshint.js b/src/jshint.js
index d452d23938..3b2f587167 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -3691,7 +3691,7 @@ var JSHINT = (function() {
     // it is a new block scope so that params can override it, it can be block scoped
     // but declarations inside the function don't cause already declared error
     state.funct["(scope)"].stack("functionouter");
-    var internallyAccessibleName = name || classExprBinding;
+    var internallyAccessibleName = !isMethod && (name || classExprBinding);
     if (internallyAccessibleName) {
       state.funct["(scope)"].block.add(internallyAccessibleName,
         classExprBinding ? "class" : "function", state.tokens.curr, false);


Test patch:
diff --git a/tests/unit/options.js b/tests/unit/options.js
index 579fd54b3c..4202991f75 100644
--- a/tests/unit/options.js
+++ b/tests/unit/options.js
@@ -1107,6 +1107,73 @@ exports.unused.crossBlocks = function (test) {
   test.done();
 };
 
+// Regression test for gh-3354
+exports.unused.methodNames = function (test) {
+  TestRun(test, "object methods - ES5")
+    .test([
+      "var p;",
+      "void {",
+      "  get p() { void p; },",
+      "  set p(_) { void p; void _; }",
+      "};"
+    ], { unused: true, esversion: 5 });
+
+  TestRun(test, "object methods - ES6")
+    .test([
+      "var m, g;",
+      "void {",
+      "  m() { void m; },",
+      "  *g() { yield g; }",
+      "};"
+    ], { unused: true, esversion: 6 });
+
+  TestRun(test, "object methods - ES8")
+    .test([
+      "var m;",
+      "void {",
+      "  async m() { void m; }",
+      "};"
+    ], { unused: true, esversion: 8 });
+
+  TestRun(test, "object methods - ES9")
+    .test([
+      "var m;",
+      "void {",
+      "  async * m() { yield m; }",
+      "};"
+    ], { unused: true, esversion: 9 });
+
+  TestRun(test, "class methods - ES6")
+    .test([
+      "var m, g, p, s;",
+      "void class {",
+      "  m() { void m; }",
+      "  *g() { yield g; }",
+      "  get p() { void p; }",
+      "  set p() { void p; }",
+      "  static s() { void s; }",
+      "};"
+    ], { unused: true, esversion: 6 });
+
+  TestRun(test, "class methods - ES8")
+    .test([
+      "var m;",
+      "void class {",
+      "  async m() { void m; }",
+      "};"
+    ], { unused: true, esversion: 8 });
+
+  TestRun(test, "class methods - ES9")
+    .test([
+      "var m;",
+      "void class {",
+      "  async * m() { yield m; }",
+      "};"
+    ], { unused: true, esversion: 9 });
+
+  test.done();
+};
+
 exports['param overrides function name expression'] = function (test) {
   TestRun(test)
     .test([