diff --git a/CHANGELOG.md b/CHANGELOG.md index bc3fc1918d..b81ad61a61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange ## [Unreleased] +## [2.29.1] - 2023-12-14 + +### Fixed +- [`no-extraneous-dependencies`]: ignore `export type { ... } from '...'` when `includeTypes` is `false` ([#2919], thanks [@Pandemic1617]) +- [`no-unused-modules`]: support export patterns with array destructuring ([#2930], thanks [@ljharb]) +- [Deps] update `tsconfig-paths` ([#2447], thanks [@domdomegg]) + ## [2.29.0] - 2023-10-22 ### Added @@ -1094,6 +1101,7 @@ for info on changes for earlier releases. [`memo-parser`]: ./memo-parser/README.md +[#2919]: https://github.com/import-js/eslint-plugin-import/pull/2919 [#2884]: https://github.com/import-js/eslint-plugin-import/pull/2884 [#2854]: https://github.com/import-js/eslint-plugin-import/pull/2854 [#2851]: https://github.com/import-js/eslint-plugin-import/pull/2851 @@ -1431,6 +1439,8 @@ for info on changes for earlier releases. [#211]: https://github.com/import-js/eslint-plugin-import/pull/211 [#164]: https://github.com/import-js/eslint-plugin-import/pull/164 [#157]: https://github.com/import-js/eslint-plugin-import/pull/157 + +[#2930]: https://github.com/import-js/eslint-plugin-import/issues/2930 [#2687]: https://github.com/import-js/eslint-plugin-import/issues/2687 [#2684]: https://github.com/import-js/eslint-plugin-import/issues/2684 [#2674]: https://github.com/import-js/eslint-plugin-import/issues/2674 @@ -1438,6 +1448,7 @@ for info on changes for earlier releases. [#2666]: https://github.com/import-js/eslint-plugin-import/issues/2666 [#2665]: https://github.com/import-js/eslint-plugin-import/issues/2665 [#2577]: https://github.com/import-js/eslint-plugin-import/issues/2577 +[#2447]: https://github.com/import-js/eslint-plugin-import/issues/2447 [#2444]: https://github.com/import-js/eslint-plugin-import/issues/2444 [#2412]: https://github.com/import-js/eslint-plugin-import/issues/2412 [#2392]: https://github.com/import-js/eslint-plugin-import/issues/2392 @@ -1556,7 +1567,8 @@ for info on changes for earlier releases. [#119]: https://github.com/import-js/eslint-plugin-import/issues/119 [#89]: https://github.com/import-js/eslint-plugin-import/issues/89 -[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.0...HEAD +[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.1...HEAD +[2.29.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.29.0...v2.29.1 [2.29.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.1...v2.29.0 [2.28.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.28.0...v2.28.1 [2.28.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.27.5...v2.28.0 @@ -1708,6 +1720,7 @@ for info on changes for earlier releases. [@devinrhode2]: https://github.com/devinrhode2 [@devongovett]: https://github.com/devongovett [@dmnd]: https://github.com/dmnd +[@domdomegg]: https://github.com/domdomegg [@duncanbeevers]: https://github.com/duncanbeevers [@dwardu]: https://github.com/dwardu [@echenley]: https://github.com/echenley @@ -1830,6 +1843,7 @@ for info on changes for earlier releases. [@ntdb]: https://github.com/ntdb [@nwalters512]: https://github.com/nwalters512 [@ombene]: https://github.com/ombene +[@Pandemic1617]: https://github.com/Pandemic1617 [@ota-meshi]: https://github.com/ota-meshi [@OutdatedVersion]: https://github.com/OutdatedVersion [@panrafal]: https://github.com/panrafal diff --git a/package.json b/package.json index bd92f4f692..5c0af48543 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-import", - "version": "2.29.0", + "version": "2.29.1", "description": "Import with sanity.", "engines": { "node": ">=4" @@ -69,11 +69,11 @@ "babel-preset-flow": "^6.23.0", "babel-register": "^6.26.0", "babylon": "^6.18.0", - "chai": "^4.3.7", + "chai": "^4.3.10", "cross-env": "^4.0.0", "escope": "^3.6.0", "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", - "eslint-doc-generator": "^1.4.3", + "eslint-doc-generator": "^1.6.1", "eslint-import-resolver-node": "file:./resolvers/node", "eslint-import-resolver-typescript": "^1.0.2 || ^1.1.1", "eslint-import-resolver-webpack": "file:./resolvers/webpack", @@ -88,7 +88,7 @@ "jackspeak": "=2.1.1", "linklocal": "^2.8.2", "lodash.isarray": "^4.0.0", - "markdownlint-cli": "^0.35.0", + "markdownlint-cli": "^0.38.0", "mocha": "^3.5.3", "npm-which": "^3.0.1", "nyc": "^11.9.0", @@ -119,6 +119,6 @@ "object.groupby": "^1.0.1", "object.values": "^1.1.7", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "tsconfig-paths": "^3.15.0" } } diff --git a/src/rules/no-extraneous-dependencies.js b/src/rules/no-extraneous-dependencies.js index 0408e0866d..df97987901 100644 --- a/src/rules/no-extraneous-dependencies.js +++ b/src/rules/no-extraneous-dependencies.js @@ -177,6 +177,7 @@ function reportIfMissing(context, deps, depsOptions, node, name) { && ( node.importKind === 'type' || node.importKind === 'typeof' + || node.exportKind === 'type' || Array.isArray(node.specifiers) && node.specifiers.length && node.specifiers.every((specifier) => specifier.importKind === 'type' || specifier.importKind === 'typeof') ) ) { diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js index ecba3a19ce..8229d880ce 100644 --- a/src/rules/no-unused-modules.js +++ b/src/rules/no-unused-modules.js @@ -74,6 +74,7 @@ const FUNCTION_DECLARATION = 'FunctionDeclaration'; const CLASS_DECLARATION = 'ClassDeclaration'; const IDENTIFIER = 'Identifier'; const OBJECT_PATTERN = 'ObjectPattern'; +const ARRAY_PATTERN = 'ArrayPattern'; const TS_INTERFACE_DECLARATION = 'TSInterfaceDeclaration'; const TS_TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration'; const TS_ENUM_DECLARATION = 'TSEnumDeclaration'; @@ -97,6 +98,10 @@ function forEachDeclarationIdentifier(declaration, cb) { cb(pattern.name); } }); + } else if (id.type === ARRAY_PATTERN) { + id.elements.forEach(({ name }) => { + cb(name); + }); } else { cb(id.name); } diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js index d61fda86e1..f83221105a 100644 --- a/tests/src/rules/no-duplicates.js +++ b/tests/src/rules/no-duplicates.js @@ -482,6 +482,68 @@ import {x,y} from './foo' errors: ["'../constants' imported multiple times.", "'../constants' imported multiple times."], ...jsxConfig, }), + + test({ + code: ` + import {A1,} from 'foo'; + import {B1,} from 'foo'; + import {C1,} from 'foo'; + + import { + A2, + } from 'bar'; + import { + B2, + } from 'bar'; + import { + C2, + } from 'bar'; + + `, + output: ` + import {A1,B1,C1} from 'foo'; + ${''} + import { + A2, + ${''} + B2, + C2} from 'bar'; + ${''} + `, + errors: [ + { + message: "'foo' imported multiple times.", + line: 2, + column: 27, + }, + { + message: "'foo' imported multiple times.", + line: 3, + column: 27, + }, + { + message: "'foo' imported multiple times.", + line: 4, + column: 27, + }, + { + message: "'bar' imported multiple times.", + line: 8, + column: 16, + }, + { + message: "'bar' imported multiple times.", + line: 11, + column: 16, + }, + { + message: "'bar' imported multiple times.", + line: 14, + column: 16, + }, + ], + ...jsxConfig, + }), ], }); diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js index 21561615c6..cb0398ada2 100644 --- a/tests/src/rules/no-extraneous-dependencies.js +++ b/tests/src/rules/no-extraneous-dependencies.js @@ -427,6 +427,18 @@ describe('TypeScript', () => { options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }], ...parserConfig, }), + + test({ + code: 'import type { T } from "a"; export type { T };', + options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }], + ...parserConfig, + }), + + test({ + code: 'export type { T } from "a";', + options: [{ packageDir: packageDirWithTypescriptDevDependencies, devDependencies: false }], + ...parserConfig, + }), ], invalid: [ test({ diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js index 77fb608ccb..b09d5d759c 100644 --- a/tests/src/rules/no-unused-modules.js +++ b/tests/src/rules/no-unused-modules.js @@ -160,6 +160,15 @@ ruleTester.run('no-unused-modules', rule, { filename: testFilePath('./no-unused-modules/file-o.js'), parser: parsers.BABEL_OLD, }), + test({ + options: unusedExportsOptions, + code: ` + export const [o0, o2] = createLoadingAndErrorSelectors( + AUTH_USER + ); + `, + filename: testFilePath('./no-unused-modules/file-o.js'), + }), ], invalid: [ test({ @@ -723,7 +732,7 @@ describe('renameDefault', () => { describe('test behavior for new file', () => { before(() => { - fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', { encoding: 'utf8' }); + fs.writeFileSync(testFilePath('./no-unused-modules/file-added-0.js'), '', { encoding: 'utf8', flag: 'w' }); }); // add import in newly created file @@ -831,7 +840,7 @@ describe('test behavior for new file', () => { describe('test behavior for new file', () => { before(() => { - fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', { encoding: 'utf8' }); + fs.writeFileSync(testFilePath('./no-unused-modules/file-added-1.js'), '', { encoding: 'utf8', flag: 'w' }); }); ruleTester.run('no-unused-modules', rule, { valid: [ @@ -866,7 +875,7 @@ describe('test behavior for new file', () => { describe('test behavior for new file', () => { before(() => { - fs.writeFileSync(testFilePath('./no-unused-modules/file-added-2.js'), '', { encoding: 'utf8' }); + fs.writeFileSync(testFilePath('./no-unused-modules/file-added-2.js'), '', { encoding: 'utf8', flag: 'w' }); }); ruleTester.run('no-unused-modules', rule, { valid: [ @@ -892,7 +901,7 @@ describe('test behavior for new file', () => { describe('test behavior for new file', () => { before(() => { - fs.writeFileSync(testFilePath('./no-unused-modules/file-added-3.js'), '', { encoding: 'utf8' }); + fs.writeFileSync(testFilePath('./no-unused-modules/file-added-3.js'), '', { encoding: 'utf8', flag: 'w' }); }); ruleTester.run('no-unused-modules', rule, { valid: [ @@ -943,7 +952,7 @@ describe('test behavior for destructured exports', () => { describe('test behavior for new file', () => { before(() => { - fs.writeFileSync(testFilePath('./no-unused-modules/file-added-4.js.js'), '', { encoding: 'utf8' }); + fs.writeFileSync(testFilePath('./no-unused-modules/file-added-4.js.js'), '', { encoding: 'utf8', flag: 'w' }); }); ruleTester.run('no-unused-modules', rule, { valid: [