Repository: import-js/eslint-plugin-import (JavaScript)

Issue:
no-unused-modules does not work with `export class`
`index.js`:

```js
import { Example } from './foo.js'
export { Example }
```

`foo.js`:

```js
export class Example {}
```

`.eslintrc.yml`:

```yml
parserOptions:
  ecmaVersion: 2019
  sourceType: module
plugins: [import]
rules:
  import/no-unused-modules: [2, {missingExports: true}]
```

Then:

```bash
$ eslint
/home/user/example/foo.js
  1:1  error  No exports found                                 import/no-unused-modules

✖ 1 problem (1 error, 0 warnings)
```

However the following works:

```js
class Example {}
export { Example }
```

`eslint`: `5.16.0`
`eslint-plugin-import`: `2.17.3`
`node`: `12.3.1`
OS: Ubuntu `19.04`


Discussion:
Thanks for the fix! :tada: 	
It seems like this same problem exists for `export module Example`, or am I misinterpreting?
@nathanielcook `export module` is not valid syntax.
@ljharb It is in TypeScript; sorry for not mentioning that.
In that case, please feel free to file a PR to add it :-)
By the way, I see now that the problem also exists for `export enum` and `export interface`.

Edit: `export function` as well.



Patch:
diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js
index e168aea2e3..d86afbb464 100644
--- a/src/rules/no-unused-modules.js
+++ b/src/rules/no-unused-modules.js
@@ -33,6 +33,7 @@ const IMPORT_NAMESPACE_SPECIFIER = 'ImportNamespaceSpecifier'
 const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier'
 const VARIABLE_DECLARATION = 'VariableDeclaration'
 const FUNCTION_DECLARATION = 'FunctionDeclaration'
+const CLASS_DECLARATION = 'ClassDeclaration'
 const DEFAULT = 'default'
 
 let preparationDone = false
@@ -390,7 +391,10 @@ module.exports = {
             })
           }
           if (declaration) {
-            if (declaration.type === FUNCTION_DECLARATION) {
+            if (
+              declaration.type === FUNCTION_DECLARATION ||
+              declaration.type === CLASS_DECLARATION
+            ) {
               newExportIdentifiers.add(declaration.id.name)
             }   
             if (declaration.type === VARIABLE_DECLARATION) {
@@ -712,7 +716,10 @@ module.exports = {
             checkUsage(node, specifier.exported.name)
         })
         if (node.declaration) {
-          if (node.declaration.type === FUNCTION_DECLARATION) {
+          if (
+            node.declaration.type === FUNCTION_DECLARATION ||
+            node.declaration.type === CLASS_DECLARATION
+          ) {
             checkUsage(node, node.declaration.id.name)
           }
           if (node.declaration.type === VARIABLE_DECLARATION) {


Test patch:
diff --git a/tests/files/no-unused-modules/file-0.js b/tests/files/no-unused-modules/file-0.js
index e7615ad4f6..a5319b5fcc 100644
--- a/tests/files/no-unused-modules/file-0.js
+++ b/tests/files/no-unused-modules/file-0.js
@@ -7,6 +7,7 @@ import { e } from './file-e'
 import { e2 } from './file-e'
 import { h2 } from './file-h'
 import * as l from './file-l'
+import {q} from './file-q'
 export * from './file-n'
 export { default, o0, o3 } from './file-o'
 export { p } from './file-p'
diff --git a/tests/files/no-unused-modules/file-q.js b/tests/files/no-unused-modules/file-q.js
new file mode 100644
index 0000000000..c0d4f699de
--- /dev/null
+++ b/tests/files/no-unused-modules/file-q.js
@@ -0,0 +1,3 @@
+export class q {
+  q0() {}
+}
diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js
index c9e7fde157..cefa6ff214 100644
--- a/tests/src/rules/no-unused-modules.js
+++ b/tests/src/rules/no-unused-modules.js
@@ -35,6 +35,8 @@ ruleTester.run('no-unused-modules', rule, {
            code: 'const a = 1; const b = 2; export { a, b }'}),
     test({ options: missingExportsOptions,
            code: 'const a = 1; export default a'}),
+    test({ options: missingExportsOptions,
+           code: 'export class Foo {}'}),
   ],
   invalid: [
     test({
@@ -67,6 +69,9 @@ ruleTester.run('no-unused-modules', rule, {
     test({ options: unusedExportsOptions,
            code: 'export function d() { return 4 }',
            filename: testFilePath('./no-unused-modules/file-d.js')}),
+    test({ options: unusedExportsOptions,
+           code: 'export class q { q0() {} }',
+           filename: testFilePath('./no-unused-modules/file-q.js')}),
     test({ options: unusedExportsOptions,
            code: 'const e0 = 5; export { e0 as e }',
            filename: testFilePath('./no-unused-modules/file-e.js')}),
@@ -132,6 +137,10 @@ ruleTester.run('no-unused-modules', rule, {
            code: 'export function j() { return 4 }',
            filename: testFilePath('./no-unused-modules/file-j.js'),
            errors: [error(`exported declaration 'j' not used within other modules`)]}),
+    test({ options: unusedExportsOptions,
+           code: 'export class q { q0() {} }',
+           filename: testFilePath('./no-unused-modules/file-q.js'),
+           errors: [error(`exported declaration 'q' not used within other modules`)]}),
     test({ options: unusedExportsOptions,
            code: 'const k0 = 5; export { k0 as k }',
            filename: testFilePath('./no-unused-modules/file-k.js'),