From 87b979913aa72803c58a206037837737e87f57e4 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Tue, 7 Feb 2023 03:06:41 -0600 Subject: [PATCH 1/3] feat: add no-unused-exports rule --- .README/README.md | 1 + .README/rules/no-unused-exports.md | 13 ++ README.md | 22 ++- package-lock.json | 164 +++++++++++++++++-- package.json | 1 + src/index.ts | 2 + src/rules/noUnusedExports.ts | 78 +++++++++ tests/fixtures/noUnusedExports/barUser.ts | 4 + tests/fixtures/noUnusedExports/tsconfig.json | 5 + tests/fixtures/noUnusedExports/unusedFoo.ts | 1 + tests/fixtures/noUnusedExports/usedBar.ts | 1 + tests/rules/assertions/noUnusedExports.ts | 34 ++++ tests/rules/index.ts | 1 + 13 files changed, 308 insertions(+), 19 deletions(-) create mode 100644 .README/rules/no-unused-exports.md create mode 100644 src/rules/noUnusedExports.ts create mode 100644 tests/fixtures/noUnusedExports/barUser.ts create mode 100644 tests/fixtures/noUnusedExports/tsconfig.json create mode 100644 tests/fixtures/noUnusedExports/unusedFoo.ts create mode 100644 tests/fixtures/noUnusedExports/usedBar.ts create mode 100644 tests/rules/assertions/noUnusedExports.ts diff --git a/.README/README.md b/.README/README.md index 667187d..630f660 100644 --- a/.README/README.md +++ b/.README/README.md @@ -92,6 +92,7 @@ See [ESLint documentation](https://eslint.org/docs/user-guide/configuring/config {"gitdown": "include", "file": "./rules/id-match.md"} {"gitdown": "include", "file": "./rules/import-specifier-newline.md"} {"gitdown": "include", "file": "./rules/no-restricted-strings.md"} +{"gitdown": "include", "file": "./rules/no-unused-exports.md"} {"gitdown": "include", "file": "./rules/no-use-extend-native.md"} {"gitdown": "include", "file": "./rules/prefer-import-alias.md"} {"gitdown": "include", "file": "./rules/prefer-inline-type-import.md"} diff --git a/.README/rules/no-unused-exports.md b/.README/rules/no-unused-exports.md new file mode 100644 index 0000000..89cf2ff --- /dev/null +++ b/.README/rules/no-unused-exports.md @@ -0,0 +1,13 @@ +### `no-unused-exports` + +Identifies unused exports. + +> **Note** This rule uses [`ts-unused-exports`](https://github.com/pzavolinsky/ts-unused-exports) program behind the scenes. + +#### Options + +|Config|Type|Description| +|---|---|---| +|`tsConfigPath`|string|Path to [tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)] + + diff --git a/README.md b/README.md index dec0b87..64dd15a 100644 --- a/README.md +++ b/README.md @@ -305,6 +305,24 @@ Disallow specified strings. The 1st option is an array of strings that cannot be contained in the codebase. + + +### no-unused-exports + +Identifies unused exports. + +> **Note** This rule uses [`ts-unused-exports`](https://github.com/pzavolinsky/ts-unused-exports) program behind the scenes. + + + +#### Options + +|Config|Type|Description| +|---|---|---| +|`tsConfigPath`|string|Path to [tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)] + + + ### no-use-extend-native @@ -382,8 +400,8 @@ Note: This rule is equivalent to [`sort-keys`](https://eslint.org/docs/rules/sor This rule requires identifiers in assignments and `function` definitions to match a specified regular expression. - - + + #### Options The 1st option is "asc" or "desc". diff --git a/package-lock.json b/package-lock.json index 6012579..b7205b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "is-proto-prop": "^2.0.0", "lodash": "^4.17.21", "natural-compare": "^1.4.0", + "ts-unused-exports": "^9.0.3", "xregexp": "^5.1.1" }, "devDependencies": { @@ -1814,8 +1815,7 @@ "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, "node_modules/@types/minimist": { "version": "1.2.2", @@ -8206,7 +8206,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13592,7 +13591,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, "engines": { "node": ">=4" } @@ -13943,11 +13941,97 @@ "node": ">=0.3.1" } }, + "node_modules/ts-unused-exports": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/ts-unused-exports/-/ts-unused-exports-9.0.3.tgz", + "integrity": "sha512-LCGLYL0EVdXNj1O/cGfpP2Fx+zfqoV936iMyIhvSVnXk4RUjwmSjMzzCNXI9b1j9PCs946a2TbRMhJh7/XUyUA==", + "dependencies": { + "chalk": "^4.0.0", + "tsconfig-paths": "^3.9.0" + }, + "bin": { + "ts-unused-exports": "bin/ts-unused-exports" + }, + "funding": { + "url": "https://github.com/pzavolinsky/ts-unused-exports?sponsor=1" + }, + "peerDependencies": { + "typescript": ">=3.8.3" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": false + } + } + }, + "node_modules/ts-unused-exports/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-unused-exports/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-unused-exports/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ts-unused-exports/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/ts-unused-exports/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-unused-exports/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "dev": true, "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.1", @@ -13959,7 +14043,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, "dependencies": { "minimist": "^1.2.0" }, @@ -14051,7 +14134,6 @@ "version": "4.9.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -15970,8 +16052,7 @@ "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, "@types/minimist": { "version": "1.2.2", @@ -20681,8 +20762,7 @@ "minimist": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" }, "minimist-options": { "version": "4.1.0", @@ -24546,8 +24626,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" }, "strip-final-newline": { "version": "2.0.0", @@ -24794,11 +24873,64 @@ } } }, + "ts-unused-exports": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/ts-unused-exports/-/ts-unused-exports-9.0.3.tgz", + "integrity": "sha512-LCGLYL0EVdXNj1O/cGfpP2Fx+zfqoV936iMyIhvSVnXk4RUjwmSjMzzCNXI9b1j9PCs946a2TbRMhJh7/XUyUA==", + "requires": { + "chalk": "^4.0.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "dev": true, "requires": { "@types/json5": "^0.0.29", "json5": "^1.0.1", @@ -24810,7 +24942,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, "requires": { "minimist": "^1.2.0" } @@ -24884,8 +25015,7 @@ "typescript": { "version": "4.9.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", - "dev": true + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" }, "uglify-js": { "version": "3.17.4", diff --git a/package.json b/package.json index 7a355da..599e23b 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "is-proto-prop": "^2.0.0", "lodash": "^4.17.21", "natural-compare": "^1.4.0", + "ts-unused-exports": "^9.0.3", "xregexp": "^5.1.1" }, "description": "Canonical linting rules for ESLint.", diff --git a/src/index.ts b/src/index.ts index 5b2e6ac..725612b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,7 @@ import filenameNoIndex from './rules/filenameNoIndex'; import idMatch from './rules/idMatch'; import importSpecifierNewline from './rules/importSpecifierNewline'; import noRestrictedStrings from './rules/noRestrictedStrings'; +import noUnusedExports from './rules/noUnusedExports'; import noUseExtendNative from './rules/noUseExtendNative'; import preferImportAlias from './rules/preferImportAlias'; import preferInlineTypeImport from './rules/preferInlineTypeImport'; @@ -26,6 +27,7 @@ export = { 'id-match': idMatch, 'import-specifier-newline': importSpecifierNewline, 'no-restricted-strings': noRestrictedStrings, + 'no-unused-exports': noUnusedExports, 'no-use-extend-native': noUseExtendNative, 'prefer-import-alias': preferImportAlias, 'prefer-inline-type-import': preferInlineTypeImport, diff --git a/src/rules/noUnusedExports.ts b/src/rules/noUnusedExports.ts new file mode 100644 index 0000000..ee723c2 --- /dev/null +++ b/src/rules/noUnusedExports.ts @@ -0,0 +1,78 @@ +import analyzeTsConfig from 'ts-unused-exports'; +import { createRule } from '../utilities'; + +const defaultOptions = { + tsConfigPath: '', +}; + +type Options = [ + { + tsConfigPath: string; + }, +]; + +type MessageIds = 'unusedExport'; + +export default createRule({ + create: (context) => { + const [options] = context.options; + + const result = analyzeTsConfig(options.tsConfigPath); + + return { + Program() { + const filename = context.getFilename(); + + if (!result[filename]) { + return; + } + + const sourceCode = context.getSourceCode(); + + for (const unusedExport of result[filename]) { + const index = sourceCode.getIndexFromLoc({ + column: unusedExport.location.character, + line: unusedExport.location.line, + }); + + const exportToken = sourceCode.getTokenByRangeStart(index); + + if (!exportToken) { + throw new Error('Expected export node'); + } + + context.report({ + data: { + exportName: unusedExport.exportName, + }, + messageId: 'unusedExport', + node: exportToken, + }); + } + }, + }; + }, + defaultOptions: [defaultOptions], + meta: { + docs: { + description: 'Identifies unused exports.', + recommended: false, + }, + messages: { + unusedExport: "Export '{{exportName}}' is unused.", + }, + schema: [ + { + additionalProperties: false, + properties: { + tsConfigPath: { + type: 'string', + }, + }, + type: 'object', + }, + ], + type: 'layout', + }, + name: 'no-unused-exports', +}); diff --git a/tests/fixtures/noUnusedExports/barUser.ts b/tests/fixtures/noUnusedExports/barUser.ts new file mode 100644 index 0000000..bde92b4 --- /dev/null +++ b/tests/fixtures/noUnusedExports/barUser.ts @@ -0,0 +1,4 @@ +import { BAR } from './usedBar'; + +// eslint-disable-next-line no-console +console.log(BAR); diff --git a/tests/fixtures/noUnusedExports/tsconfig.json b/tests/fixtures/noUnusedExports/tsconfig.json new file mode 100644 index 0000000..102110d --- /dev/null +++ b/tests/fixtures/noUnusedExports/tsconfig.json @@ -0,0 +1,5 @@ +{ + "include": [ + ".", + ] +} \ No newline at end of file diff --git a/tests/fixtures/noUnusedExports/unusedFoo.ts b/tests/fixtures/noUnusedExports/unusedFoo.ts new file mode 100644 index 0000000..4083521 --- /dev/null +++ b/tests/fixtures/noUnusedExports/unusedFoo.ts @@ -0,0 +1 @@ +export const FOO = ''; diff --git a/tests/fixtures/noUnusedExports/usedBar.ts b/tests/fixtures/noUnusedExports/usedBar.ts new file mode 100644 index 0000000..6e168b3 --- /dev/null +++ b/tests/fixtures/noUnusedExports/usedBar.ts @@ -0,0 +1 @@ +export const BAR = ''; diff --git a/tests/rules/assertions/noUnusedExports.ts b/tests/rules/assertions/noUnusedExports.ts new file mode 100644 index 0000000..f8c9b08 --- /dev/null +++ b/tests/rules/assertions/noUnusedExports.ts @@ -0,0 +1,34 @@ +import { readFileSync } from 'node:fs'; +import path from 'node:path'; + +const fixturesPath = path.resolve(__dirname, '../../fixtures/noUnusedExports'); + +export default { + invalid: [ + { + code: readFileSync(path.resolve(fixturesPath, 'unusedFoo.ts'), 'utf8'), + errors: [ + { + message: "Export 'FOO' is unused.", + }, + ], + filename: path.resolve(fixturesPath, 'unusedFoo.ts'), + options: [ + { + tsConfigPath: path.resolve(fixturesPath, 'tsconfig.json'), + }, + ], + }, + ], + valid: [ + { + code: readFileSync(path.resolve(fixturesPath, 'usedBar.ts'), 'utf8'), + filename: path.resolve(fixturesPath, 'usedBar.ts'), + options: [ + { + tsConfigPath: path.resolve(fixturesPath, 'tsconfig.json'), + }, + ], + }, + ], +}; diff --git a/tests/rules/index.ts b/tests/rules/index.ts index 473e50d..781d18b 100644 --- a/tests/rules/index.ts +++ b/tests/rules/index.ts @@ -19,6 +19,7 @@ const reportingRules = [ 'id-match', 'import-specifier-newline', 'no-restricted-strings', + 'no-unused-exports', 'no-use-extend-native', 'prefer-import-alias', 'prefer-inline-type-import', From ad22fe4ca4d25615d4bcf3bbcc67a341207ec0ed Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Tue, 7 Feb 2023 03:17:13 -0600 Subject: [PATCH 2/3] feat: add no-unused-exports rule --- .README/rules/no-unused-exports.md | 14 ++++++++------ README.md | 13 +++++++------ src/rules/noUnusedExports.ts | 22 +++++++++++++++++++++- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/.README/rules/no-unused-exports.md b/.README/rules/no-unused-exports.md index 89cf2ff..3aa30d3 100644 --- a/.README/rules/no-unused-exports.md +++ b/.README/rules/no-unused-exports.md @@ -1,13 +1,15 @@ ### `no-unused-exports` -Identifies unused exports. +Identifies unused TypeScript exports. -> **Note** This rule uses [`ts-unused-exports`](https://github.com/pzavolinsky/ts-unused-exports) program behind the scenes. +> **Note** This rule is implemented using [`ts-unused-exports`](https://github.com/pzavolinsky/ts-unused-exports). #### Options -|Config|Type|Description| -|---|---|---| -|`tsConfigPath`|string|Path to [tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)] +|Config|Type|Required|Default|Description| +|---|---|---|---|---| +|`tsConfigPath`|string|Required||Path to [tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)| +|`allowUnusedEnums`|boolean||`false`|Allow unused `enum`s.| +|`allowUnusedTypes`|boolean||`false`|Allow unused `type` and `interface`.| - + \ No newline at end of file diff --git a/README.md b/README.md index 64dd15a..65ccdec 100644 --- a/README.md +++ b/README.md @@ -309,18 +309,19 @@ The 1st option is an array of strings that cannot be contained in the codebase. ### no-unused-exports -Identifies unused exports. +Identifies unused TypeScript exports. -> **Note** This rule uses [`ts-unused-exports`](https://github.com/pzavolinsky/ts-unused-exports) program behind the scenes. +> **Note** This rule is implemented using [`ts-unused-exports`](https://github.com/pzavolinsky/ts-unused-exports). #### Options -|Config|Type|Description| -|---|---|---| -|`tsConfigPath`|string|Path to [tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)] - +|Config|Type|Required|Default|Description| +|---|---|---|---|---| +|`tsConfigPath`|string|Required||Path to [tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)| +|`allowUnusedEnums`|boolean||`false`|Allow unused `enum`s.| +|`allowUnusedTypes`|boolean||`false`|Allow unused `type` and `interface`.| diff --git a/src/rules/noUnusedExports.ts b/src/rules/noUnusedExports.ts index ee723c2..d48f6b8 100644 --- a/src/rules/noUnusedExports.ts +++ b/src/rules/noUnusedExports.ts @@ -2,11 +2,15 @@ import analyzeTsConfig from 'ts-unused-exports'; import { createRule } from '../utilities'; const defaultOptions = { + allowUnusedEnums: false, + allowUnusedTypes: false, tsConfigPath: '', }; type Options = [ { + allowUnusedEnums: boolean; + allowUnusedTypes: boolean; tsConfigPath: string; }, ]; @@ -17,7 +21,17 @@ export default createRule({ create: (context) => { const [options] = context.options; - const result = analyzeTsConfig(options.tsConfigPath); + const tsUnusedOptions: string[] = []; + + if (options.allowUnusedEnums) { + tsUnusedOptions.push('--allowUnusedEnums'); + } + + if (options.allowUnusedTypes) { + tsUnusedOptions.push('--allowUnusedTypes'); + } + + const result = analyzeTsConfig(options.tsConfigPath, tsUnusedOptions); return { Program() { @@ -65,6 +79,12 @@ export default createRule({ { additionalProperties: false, properties: { + allowUnusedEnums: { + type: 'boolean', + }, + allowUnusedTypes: { + type: 'boolean', + }, tsConfigPath: { type: 'string', }, From 465f9698ac7382bd9865034f426283c5af4c14a5 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Tue, 7 Feb 2023 03:18:43 -0600 Subject: [PATCH 3/3] feat: add no-unused-exports rule --- tests/fixtures/noUnusedExports/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fixtures/noUnusedExports/tsconfig.json b/tests/fixtures/noUnusedExports/tsconfig.json index 102110d..7e26fb2 100644 --- a/tests/fixtures/noUnusedExports/tsconfig.json +++ b/tests/fixtures/noUnusedExports/tsconfig.json @@ -1,5 +1,5 @@ { "include": [ - ".", + "." ] } \ No newline at end of file