diff --git a/bin/eslint-unused-modules.js b/bin/eslint-unused-modules.js deleted file mode 100755 index 9dc8ea38..00000000 --- a/bin/eslint-unused-modules.js +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env node - -const {CLIEngine} = require('eslint') - -// TODO: Figure out how to deactive other rules. -let cli = new CLIEngine({ - rules: { - 'github/dependency-graph': 1 - } -}) -cli.executeOnFiles(process.argv.slice(2)) - -// TODO: Figure out how to deactive other rules. -cli = new CLIEngine({ - rules: { - 'github/unused-export': 2, - 'github/unused-module': 2 - } -}) - -const report = cli.executeOnFiles(process.argv.slice(2)) -const formatter = cli.getFormatter() - -process.stdout.write(formatter(report.results)) - -if (report.errorCount > 0) { - process.exit(1) -} diff --git a/docs/rules/unused-export.md b/docs/rules/unused-export.md deleted file mode 100644 index e4114c10..00000000 --- a/docs/rules/unused-export.md +++ /dev/null @@ -1,3 +0,0 @@ -# No unused exports - -This rule means the exported function or constant was not imported by any other modules and may not be used. diff --git a/docs/rules/unused-module.md b/docs/rules/unused-module.md deleted file mode 100644 index 810f70bc..00000000 --- a/docs/rules/unused-module.md +++ /dev/null @@ -1,15 +0,0 @@ -# No unused modules - -This rule means the module was not imported by any other modules and may not be used. - -## Missing import - -The module might be new and the file just needs to be imported by another module to be activated. - -## Dead code - -The module may be dead code if the last dependent module was removed. In this case, the module can be deleted. Ensure the module does not have any initialization side effects that may still be used. - -## Entry - -The module may intended to be a public entry point which is imported by code outside of this package. In this case, the module should be designated as an entry by TODO. diff --git a/lib/dependency-graph.js b/lib/dependency-graph.js deleted file mode 100644 index d92a38ef..00000000 --- a/lib/dependency-graph.js +++ /dev/null @@ -1,67 +0,0 @@ -const readPkgUp = require('read-pkg-up') -const path = require('path') - -const dependencyGraph = new Map() -exports.dependencyGraph = dependencyGraph - -exports.entries = new Set() - -const entryWhitelist = [/\/tests?\//, /\.test\.js$/, /\.config\.js$/] - -exports.checkEntriesWhitelist = filename => { - for (const re of entryWhitelist) { - if (re.test(filename)) { - exports.entries.add(filename) - } - } -} - -const packageFile = readPkgUp.sync() - -function recordPackageEntry(entry) { - exports.entries.add(path.resolve(packageFile.path, '..', entry)) -} - -if (packageFile) { - for (const key in packageFile.packageJson) { - if (key === 'main') { - recordPackageEntry(packageFile.packageJson.main) - } else if (key === 'entries') { - packageFile.packageJson.entries.forEach(recordPackageEntry) - } else if (/-bundles$/.test(key)) { - // github-asset-pipeline internal manifest format - Object.keys(packageFile.packageJson[key]).forEach(recordPackageEntry) - } - } -} - -function gatherImported() { - const filenames = new Set() - const identifiers = new Set() - - for (const {imports} of dependencyGraph.values()) { - for (const [importedFilename, importedIdentifiers] of imports) { - // require.resolve will expand any symlinks to their fully qualified - // directories. We can use this (with the absolute path given in - // importedFilename to quickly expand symlinks, which allows us to have - // symlinks (aka workspaces) in node_modules, and not fail the lint. - const fullyQualifiedImportedFilename = require.resolve(importedFilename) - filenames.add(fullyQualifiedImportedFilename) - - for (const importedIdentifier of importedIdentifiers) { - identifiers.add(`${fullyQualifiedImportedFilename}#${importedIdentifier}`) - } - } - } - - return {filenames, identifiers} -} - -let importedCache = null - -exports.imported = function() { - if (!importedCache) { - importedCache = gatherImported() - } - return importedCache -} diff --git a/lib/index.js b/lib/index.js index a9e4139f..f1c30106 100644 --- a/lib/index.js +++ b/lib/index.js @@ -4,7 +4,6 @@ module.exports = { 'async-currenttarget': require('./rules/async-currenttarget'), 'async-preventdefault': require('./rules/async-preventdefault'), 'authenticity-token': require('./rules/authenticity-token'), - 'dependency-graph': require('./rules/dependency-graph'), 'get-attribute': require('./rules/get-attribute'), 'js-class-name': require('./rules/js-class-name'), 'no-blur': require('./rules/no-blur'), @@ -13,9 +12,7 @@ module.exports = { 'no-implicit-buggy-globals': require('./rules/no-implicit-buggy-globals'), 'no-innerText': require('./rules/no-innerText'), 'no-then': require('./rules/no-then'), - 'unescaped-html-literal': require('./rules/unescaped-html-literal'), - 'unused-export': require('./rules/unused-export'), - 'unused-module': require('./rules/unused-module') + 'unescaped-html-literal': require('./rules/unescaped-html-literal') }, configs: { app: require('./configs/app'), diff --git a/lib/rules/dependency-graph.js b/lib/rules/dependency-graph.js deleted file mode 100644 index e8304776..00000000 --- a/lib/rules/dependency-graph.js +++ /dev/null @@ -1,110 +0,0 @@ -const resolve = require('eslint-module-utils/resolve').default - -const {dependencyGraph, checkEntriesWhitelist, entries} = require('../dependency-graph') - -const STAR = '*' -const DEFAULT = 'default' - -module.exports = { - meta: { - docs: {} - }, - - create(context) { - const filename = context.getFilename() - const sourceCode = context.getSourceCode() - - const imports = new Map() - const exports = new Set() - - checkEntriesWhitelist(filename) - - function recordImport(importPath, symbol) { - let symbols = imports.get(importPath) - if (!symbols) { - symbols = new Set() - imports.set(importPath, symbols) - } - - if (symbol) { - symbols.add(symbol) - } - } - - function recordExport(symbol) { - if (symbol) { - exports.add(symbol) - } - } - - return { - ImportDeclaration(node) { - const resolvedPath = resolve(node.source.value, context) - if (!resolvedPath) { - return - } - - recordImport(resolvedPath) - - node.specifiers.forEach(specifier => { - if (specifier.type === 'ImportDefaultSpecifier') { - recordImport(resolvedPath, DEFAULT) - } else if (specifier.type === 'ImportSpecifier') { - recordImport(resolvedPath, specifier.imported.name) - } - }) - }, - ExportDefaultDeclaration() { - recordExport(DEFAULT) - }, - ExportNamedDeclaration(node) { - if (node.declaration == null) return - - if (node.declaration.id != null) { - recordExport(node.declaration.id.name) - } - - if (node.declaration.declarations != null) { - for (const declaration of node.declaration.declarations) { - recordExport(declaration.id.name) - } - } - }, - CallExpression(node) { - if (node.callee.type === 'Identifier' && node.callee.name === 'require' && node.arguments.length === 1) { - const pathNode = node.arguments[0] - if (pathNode.type === 'Literal' && typeof pathNode.value === 'string') { - const resolvedPath = - pathNode.type === 'Literal' && typeof pathNode.value === 'string' && resolve(pathNode.value, context) - - if (resolvedPath) { - recordImport(resolvedPath, STAR) - } - } - } - }, - MemberExpression(node) { - if (context.getScope().type !== 'module') { - return - } - - if (node.object.name === 'module' && node.property.name === 'exports') { - recordExport(DEFAULT) - } - - if (node.object.name === 'exports') { - recordExport(node.property.name) - } - }, - Program() { - const comments = sourceCode.getAllComments() - if (comments.some(token => token.type === 'Shebang')) { - entries.add(filename) - } - }, - 'Program:exit': function() { - dependencyGraph.set(filename, {imports, exports}) - } - } - } -} diff --git a/lib/rules/unused-export.js b/lib/rules/unused-export.js deleted file mode 100644 index 7a37a903..00000000 --- a/lib/rules/unused-export.js +++ /dev/null @@ -1,56 +0,0 @@ -const depGraph = require('../dependency-graph') - -module.exports = { - meta: { - docs: {} - }, - - create(context) { - const filename = context.getFilename() - const {identifiers} = depGraph.imported() - - if (depGraph.entries.has(filename)) { - return {} - } - - if (identifiers.has(`${filename}#*`)) { - return {} - } - - return { - ExportDefaultDeclaration(node) { - if (!identifiers.has(`${filename}#default`)) { - context.report(node, 'Export was not imported by any modules.') - } - }, - ExportNamedDeclaration(node) { - if (node.declaration == null) return - - if (node.declaration.id != null) { - if (!identifiers.has(`${filename}#${node.declaration.id.name}`)) { - context.report(node, 'Export was not imported by any modules.') - } - } - - if (node.declaration.declarations != null) { - for (const declaration of node.declaration.declarations) { - if (!identifiers.has(`${filename}#${declaration.id.name}`)) { - context.report(node, 'Export was not imported by any modules.') - } - } - } - }, - MemberExpression(node) { - if (context.getScope().type !== 'module') { - return - } - - if (node.object.name === 'exports') { - if (!identifiers.has(`${filename}#${node.property.name}`)) { - context.report(node.parent, 'Export was not imported by any modules.') - } - } - } - } - } -} diff --git a/lib/rules/unused-module.js b/lib/rules/unused-module.js deleted file mode 100644 index 7426479e..00000000 --- a/lib/rules/unused-module.js +++ /dev/null @@ -1,24 +0,0 @@ -const depGraph = require('../dependency-graph') - -module.exports = { - meta: { - docs: {} - }, - - create(context) { - const filename = context.getFilename() - - if (depGraph.entries.has(filename)) { - return {} - } - - return { - Program(node) { - const {filenames} = depGraph.imported() - if (!filenames.has(filename)) { - context.report(node, 'Module was not imported by any files.') - } - } - } - } -} diff --git a/package.json b/package.json index 01b2b383..f2ab0817 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "bin": { "eslint-github-init": "bin/eslint-github-init.js", "eslint-ignore-errors": "bin/eslint-ignore-errors.js", - "eslint-unused-modules": "bin/eslint-unused-modules.js", "github-lint": "bin/github-lint.js", "npm-check-github-package-requirements": "bin/npm-check-github-package-requirements.js" }, diff --git a/tests/dependency-graph.js b/tests/dependency-graph.js deleted file mode 100644 index d0f49ebb..00000000 --- a/tests/dependency-graph.js +++ /dev/null @@ -1,48 +0,0 @@ -const dependencyGraph = require('../lib/dependency-graph') -const assert = require('assert') -const {describe, it, before, after} = require('mocha') -const rimraf = require('rimraf') -const {resolve} = require('path') -const {mkdirSync, writeFileSync, symlinkSync} = require('fs') -describe('dependency-graph', () => { - it('has entries set', () => { - assert(dependencyGraph.entries instanceof Set) - }) - it('has dependencyGraph map', () => { - assert(dependencyGraph.dependencyGraph instanceof Map) - }) - it('has imported function', () => { - assert.equal(typeof dependencyGraph.imported, 'function') - }) - describe('imported', () => { - before(() => { - rimraf.sync('./fixtures') - mkdirSync('./fixtures') - writeFileSync('./fixtures/index.js', ``) - writeFileSync('./fixtures/one.js', ``) - symlinkSync('./fixtures/one.js', './fixtures/link.js') - const graph = {imports: new Map(), exports: new Set()} - graph.imports.set(resolve('./fixtures/one.js'), new Set(['a', 'b'])) - dependencyGraph.dependencyGraph.set('./fixtures/index.js', graph) - }) - after(() => { - rimraf.sync('./fixtures') - dependencyGraph.dependencyGraph.clear() - }) - it('gathers all imported files from dependencyGraph', () => { - const {filenames} = dependencyGraph.imported() - assert.deepEqual([...filenames], [resolve('./fixtures/one.js')]) - }) - it('gathers all imported identifiers from dependencyGraph', () => { - const {identifiers} = dependencyGraph.imported() - assert.deepEqual([...identifiers], [resolve('./fixtures/one.js#a'), resolve('./fixtures/one.js#b')]) - }) - it('follows symlinks', () => { - const graph = dependencyGraph.dependencyGraph.get('./fixtures/index.js') - graph.imports.delete('./fixtures/one.js') - graph.imports.set('./fixtures/link.js', new Set(['a', 'b'])) - const {filenames} = dependencyGraph.imported() - assert.deepEqual([...filenames], [resolve('./fixtures/one.js')]) - }) - }) -}) diff --git a/tests/unused-export.js b/tests/unused-export.js deleted file mode 100644 index 0bafa5d7..00000000 --- a/tests/unused-export.js +++ /dev/null @@ -1,95 +0,0 @@ -const {describe, beforeEach, afterEach} = require('mocha') -const depGraph = require('../lib/dependency-graph') -var rule = require('../lib/rules/unused-export') -var RuleTester = require('eslint').RuleTester -var ruleTester = new RuleTester() - -describe('dependency-graph', () => { - const originalDepGraphImport = depGraph.imported - beforeEach(() => { - depGraph.imported = () => ({ - identifiers: new Set(['a.js#*', 'b.js#foo', 'c.js#default']) - }) - }) - - afterEach(() => { - depGraph.imported = originalDepGraphImport - }) - - ruleTester.run('unused-export', rule, { - valid: [ - { - code: 'export const foo = 1', - parserOptions: {ecmaVersion: 2015, sourceType: 'module'}, - filename: 'a.js' - }, - { - code: 'export const foo = 1', - parserOptions: {ecmaVersion: 2015, sourceType: 'module'}, - filename: 'b.js' - }, - { - code: 'export default 1', - parserOptions: {ecmaVersion: 2015, sourceType: 'module'}, - filename: 'c.js' - } - ], - invalid: [ - { - code: 'export default 1', - parserOptions: {ecmaVersion: 2015, sourceType: 'module'}, - filename: 'b.js', - errors: [ - { - message: 'Export was not imported by any modules.', - type: 'ExportDefaultDeclaration' - } - ] - }, - { - code: 'export const bar = 1', - parserOptions: {ecmaVersion: 2015, sourceType: 'module'}, - filename: 'b.js', - errors: [ - { - message: 'Export was not imported by any modules.', - type: 'ExportNamedDeclaration' - } - ] - }, - { - code: 'export const foo = 1', - parserOptions: {ecmaVersion: 2015, sourceType: 'module'}, - filename: 'c.js', - errors: [ - { - message: 'Export was not imported by any modules.', - type: 'ExportNamedDeclaration' - } - ] - }, - { - code: 'export default 1', - parserOptions: {ecmaVersion: 2015, sourceType: 'module'}, - filename: 'd.js', - errors: [ - { - message: 'Export was not imported by any modules.', - type: 'ExportDefaultDeclaration' - } - ] - }, - { - code: 'export const foo = 1', - parserOptions: {ecmaVersion: 2015, sourceType: 'module'}, - filename: 'd.js', - errors: [ - { - message: 'Export was not imported by any modules.', - type: 'ExportNamedDeclaration' - } - ] - } - ] - }) -}) diff --git a/tests/unused-module.js b/tests/unused-module.js deleted file mode 100644 index 189bcab7..00000000 --- a/tests/unused-module.js +++ /dev/null @@ -1,45 +0,0 @@ -const {describe, beforeEach, afterEach} = require('mocha') -const depGraph = require('../lib/dependency-graph') -var rule = require('../lib/rules/unused-module') -var RuleTester = require('eslint').RuleTester -var ruleTester = new RuleTester() - -describe('dependency-graph', () => { - const originalDepGraphImport = depGraph.imported - beforeEach(() => { - depGraph.entries.add('a.js') - depGraph.imported = () => ({ - filenames: new Set(['b.js']) - }) - }) - - afterEach(() => { - depGraph.entries.clear() - depGraph.imported = originalDepGraphImport - }) - - ruleTester.run('unused-modules', rule, { - valid: [ - { - code: 'foo', - filename: 'a.js' - }, - { - code: 'foo', - filename: 'b.js' - } - ], - invalid: [ - { - code: 'foo', - filename: 'c.js', - errors: [ - { - message: 'Module was not imported by any files.', - type: 'Program' - } - ] - } - ] - }) -})