diff --git a/.github/workflows/node-4+.yml b/.github/workflows/node-4+.yml index 6456762fce..b13e3b88cf 100644 --- a/.github/workflows/node-4+.yml +++ b/.github/workflows/node-4+.yml @@ -33,6 +33,11 @@ jobs: - 3 - 2 include: + - node-version: 'lts/*' + eslint: 7 + ts-parser: 3 + env: + TS_PARSER: 3 - node-version: 'lts/*' eslint: 7 ts-parser: 2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4991b7a9a4..355985a816 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,18 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel ## [Unreleased] +## [2.24.2] - 2021-08-24 + +### Fixed +- [`named`], [`namespace`]: properly handle ExportAllDeclarations ([#2199], thanks [@ljharb]) + ## [2.24.1] - 2021-08-19 ### Fixed - `ExportMap`: Add default export when esModuleInterop is true and anything is exported ([#2184], thanks [@Maxim-Mazurok]) - [`named`], [`namespace`]: properly set reexports on `export * as … from` ([#1998], [#2161], thanks [@ljharb]) - [`no-duplicates`]: correctly handle case of mixed default/named type imports ([#2149], thanks [@GoodForOneFare], [@nwalters512]) +- [`no-duplicates`]: avoid crash with empty `import type {}` ([#2201], thanks [@ljharb]) ### Changed - [Docs] `max-dependencies`: 📖 Document `ignoreTypeImports` option ([#2196], thanks [@himynameisdave]) @@ -1150,6 +1156,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 +[#2201]: https://github.com/import-js/eslint-plugin-import/issues/2201 +[#2199]: https://github.com/import-js/eslint-plugin-import/issues/2199 [#2161]: https://github.com/import-js/eslint-plugin-import/issues/2161 [#2118]: https://github.com/import-js/eslint-plugin-import/issues/2118 [#2067]: https://github.com/import-js/eslint-plugin-import/issues/2067 @@ -1259,8 +1267,9 @@ 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.24.1...HEAD -[2.24.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.0...v2.24.1 +[Unreleased]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.2...HEAD +[2.24.2]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.1...v2.24.2 +[2.24.1]: https://github.com/import-js/eslint-plugin-import/compare/v2.24.0...v2.24.1 [2.24.0]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.4...v2.24.0 [2.23.4]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.3...v2.23.4 [2.23.3]: https://github.com/import-js/eslint-plugin-import/compare/v2.23.2...v2.23.3 diff --git a/README.md b/README.md index 964c123a7e..d800cbfe57 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # eslint-plugin-import -[![build status](https://travis-ci.org/import-js/eslint-plugin-import.svg?branch=master)](https://travis-ci.org/import-js/eslint-plugin-import) -[![Coverage Status](https://coveralls.io/repos/github/import-js/eslint-plugin-import/badge.svg?branch=master)](https://coveralls.io/github/import-js/eslint-plugin-import?branch=master) -[![win32 build status](https://ci.appveyor.com/api/projects/status/3mw2fifalmjlqf56/branch/master?svg=true)](https://ci.appveyor.com/project/import-js/eslint-plugin-import/branch/master) +[![github actions][actions-image]][actions-url] +[![travis-ci](https://travis-ci.org/import-js/eslint-plugin-import.svg?branch=main)](https://travis-ci.org/import-js/eslint-plugin-import) +[![coverage][codecov-image]][codecov-url] +[![win32 build status](https://ci.appveyor.com/api/projects/status/3mw2fifalmjlqf56/branch/main?svg=true)](https://ci.appveyor.com/project/import-js/eslint-plugin-import/branch/main) [![npm](https://img.shields.io/npm/v/eslint-plugin-import.svg)](https://www.npmjs.com/package/eslint-plugin-import) [![npm downloads](https://img.shields.io/npm/dt/eslint-plugin-import.svg?maxAge=2592000)](http://www.npmtrends.com/eslint-plugin-import) @@ -171,7 +172,7 @@ extends: - plugin:import/typescript # this line does the trick ``` -[`@typescript-eslint/parser`]: https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser +[`@typescript-eslint/parser`]: https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser # Resolvers @@ -510,3 +511,8 @@ In Package Settings / SublimeLinter / User Settings: I believe this defaults to `3`, so you may not need to alter it depending on your project folder max depth. + +[codecov-image]: https://codecov.io/gh/import-js/eslint-plugin-import/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/import-js/eslint-plugin-import/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/import-js/eslint-plugin-import +[actions-url]: https://github.com/import-js/eslint-plugin-import diff --git a/RELEASE.md b/RELEASE.md index 34ef1aadc6..6c048dc093 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,9 +1,9 @@ # Release steps -1. create a `release-[x.y.z]` branch from tip of `master` (or whatever release commit) +1. create a `release-[x.y.z]` branch from tip of `main` (or whatever release commit) ```bash - git checkout master && git pull && git checkout -b release-2.1.0 + git checkout main && git pull && git checkout -b release-2.1.0 ``` 2. bump `package.json` + update CHANGELOG version links for all releasing packages (i.e., root + any resolvers) @@ -49,6 +49,6 @@ 7. merge `release-[x.y.z]` into `release` ( - ideally fast-forward, probably with Git CLI instead of Github -8. merge `release` into `master` +8. merge `release` into `main` Done! diff --git a/docs/rules/imports-first.md b/docs/rules/imports-first.md index e4cdda1151..7dadffa684 100644 --- a/docs/rules/imports-first.md +++ b/docs/rules/imports-first.md @@ -1,3 +1,3 @@ # imports-first -This rule was **deprecated** in eslint-plugin-import v2.0.0. Please use the corresponding rule [`first`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/first.md). +This rule was **deprecated** in eslint-plugin-import v2.0.0. Please use the corresponding rule [`first`](https://github.com/import-js/eslint-plugin-import/blob/HEAD/docs/rules/first.md). diff --git a/docs/rules/unambiguous.md b/docs/rules/unambiguous.md index 7955c3fbc8..92839b0c35 100644 --- a/docs/rules/unambiguous.md +++ b/docs/rules/unambiguous.md @@ -51,4 +51,4 @@ a `module`. - [node-eps#13](https://github.com/nodejs/node-eps/issues/13) [`parserOptions.sourceType`]: http://eslint.org/docs/user-guide/configuring#specifying-parser-options -[Unambiguous JavaScript Grammar]: https://github.com/nodejs/node-eps/blob/master/002-es-modules.md#32-determining-if-source-is-an-es-module +[Unambiguous JavaScript Grammar]: https://github.com/nodejs/node-eps/blob/HEAD/002-es-modules.md#32-determining-if-source-is-an-es-module diff --git a/package.json b/package.json index df42105dfa..dd7cbcb350 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-import", - "version": "2.24.1", + "version": "2.24.2", "description": "Import with sanity.", "engines": { "node": ">=4" @@ -56,7 +56,7 @@ "devDependencies": { "@eslint/import-test-order-redirect-scoped": "file:./tests/files/order-redirect-scoped", "@test-scope/some-module": "file:./tests/files/symlinked-module", - "@typescript-eslint/parser": "^2.23.0 || ^3.3.0", + "@typescript-eslint/parser": "^2.23.0 || ^3.3.0 || ^4.29.3", "array.prototype.flatmap": "^1.2.4", "babel-cli": "^6.26.0", "babel-core": "^6.26.3", @@ -114,6 +114,6 @@ "pkg-up": "^2.0.0", "read-pkg-up": "^3.0.0", "resolve": "^1.20.0", - "tsconfig-paths": "^3.10.1" + "tsconfig-paths": "^3.11.0" } } diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json index 1e9fdd3ab1..fd805af8b7 100644 --- a/resolvers/webpack/package.json +++ b/resolvers/webpack/package.json @@ -30,7 +30,7 @@ "bugs": { "url": "https://github.com/import-js/eslint-plugin-import/issues" }, - "homepage": "https://github.com/import-js/eslint-plugin-import/tree/master/resolvers/webpack", + "homepage": "https://github.com/import-js/eslint-plugin-import/tree/HEAD/resolvers/webpack", "dependencies": { "array-find": "^1.0.0", "debug": "^3.2.7", diff --git a/src/ExportMap.js b/src/ExportMap.js index f49841835b..5bda83dd35 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -421,7 +421,7 @@ ExportMap.parse = function (path, content, context) { switch (s.type) { case 'ExportDefaultSpecifier': - if (!n.source) return; + if (!nsource) return; local = 'default'; break; case 'ExportNamespaceSpecifier': @@ -430,8 +430,8 @@ ExportMap.parse = function (path, content, context) { })); return; case 'ExportAllDeclaration': - local = s.exported ? s.exported.name : s.local.name; - break; + m.namespace.set(s.exported.name, addNamespace(exportMeta, s.source.value)); + return; case 'ExportSpecifier': if (!n.source) { m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local)); diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js index 08d29a0cdb..98f759cbc2 100644 --- a/src/rules/no-commonjs.js +++ b/src/rules/no-commonjs.js @@ -33,7 +33,7 @@ function validateScope(scope) { return scope.variableScope.type === 'module'; } -// https://github.com/estree/estree/blob/master/es5.md +// https://github.com/estree/estree/blob/HEAD/es5.md function isConditional(node) { if ( node.type === 'IfStatement' diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js index 6344101970..6e03fcaef0 100644 --- a/src/rules/no-duplicates.js +++ b/src/rules/no-duplicates.js @@ -281,7 +281,7 @@ module.exports = { function getImportMap(n) { if (n.importKind === 'type') { - return n.specifiers[0].type === 'ImportDefaultSpecifier' ? defaultTypesImported : namedTypesImported; + return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? defaultTypesImported : namedTypesImported; } return hasNamespace(n) ? nsImported : imported; diff --git a/tests/dep-time-travel.sh b/tests/dep-time-travel.sh index ad00568e4c..d6f5aedfc2 100755 --- a/tests/dep-time-travel.sh +++ b/tests/dep-time-travel.sh @@ -8,10 +8,16 @@ export NPM_CONFIG_LEGACY_PEER_DEPS=true npm install --no-save "eslint@${ESLINT_VERSION}" --ignore-scripts -# completely remove the new TypeScript parser for ESLint < v5 -if [[ "$ESLINT_VERSION" -lt "5" ]]; then + + +if [[ -n "$TS_PARSER" ]]; then # if TS parser is manually set, always use it + echo "Downgrading @typescript-eslint/parser..." + npm i --no-save "@typescript-eslint/parser@${TS_PARSER}" +elif [[ "$ESLINT_VERSION" -lt "5" ]]; then # completely remove the new TypeScript parser for ESLint < v5 echo "Removing @typescript-eslint/parser..." npm uninstall --no-save @typescript-eslint/parser +elif [[ "$TRAVIS_NODE_VERSION" -lt "10" ]]; then # TS parser 3 requires node 10+ + npm i --no-save "@typescript-eslint/parser@3" fi # use these alternate TypeScript dependencies for ESLint < v4 @@ -28,8 +34,3 @@ if [[ "$TRAVIS_NODE_VERSION" -lt "8" ]]; then echo "Downgrading eslint-import-resolver-typescript..." npm i --no-save eslint-import-resolver-typescript@1.0.2 fi - -if [[ -n "$TS_PARSER" ]]; then - echo "Downgrading @typescript-eslint/parser..." - npm i --no-save @typescript-eslint/parser@2 -fi diff --git a/tests/files/export-star-3/b.ts b/tests/files/export-star-3/b.ts new file mode 100644 index 0000000000..5a91d016fb --- /dev/null +++ b/tests/files/export-star-3/b.ts @@ -0,0 +1 @@ +export * as b from './c'; diff --git a/tests/files/export-star-3/c.ts b/tests/files/export-star-3/c.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js index 0d8c0b7edf..56babfa509 100644 --- a/tests/src/rules/named.js +++ b/tests/src/rules/named.js @@ -352,105 +352,91 @@ ruleTester.run('named (export *)', rule, { context('TypeScript', function () { getTSParsers().forEach((parser) => { + const settings = { + 'import/parsers': { [parser]: ['.ts'] }, + 'import/resolver': { 'eslint-import-resolver-typescript': true }, + }; + + const valid = []; + const invalid = [ + test({ + code: `import {a} from './export-star-3/b';`, + filename: testFilePath('./export-star-3/a.js'), + parser: parser, + settings: settings, + }), + ]; + [ 'typescript', 'typescript-declare', 'typescript-export-assign-namespace', 'typescript-export-assign-namespace-merged', ].forEach((source) => { - ruleTester.run(`named`, rule, { - valid: [ - test({ - code: `import { MyType } from "./${source}"`, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: `import { Foo } from "./${source}"`, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: `import { Bar } from "./${source}"`, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: `import { getFoo } from "./${source}"`, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: `import { MyEnum } from "./${source}"`, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: ` + valid.push( + test({ + code: `import { MyType } from "./${source}"`, + parser: parser, + settings: settings, + }), + test({ + code: `import { Foo } from "./${source}"`, + parser: parser, + settings: settings, + }), + test({ + code: `import { Bar } from "./${source}"`, + parser: parser, + settings: settings, + }), + test({ + code: `import { getFoo } from "./${source}"`, + parser: parser, + settings: settings, + }), + test({ + code: `import { MyEnum } from "./${source}"`, + parser: parser, + settings: settings, + }), + test({ + code: ` import { MyModule } from "./${source}" MyModule.ModuleFunction() `, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: ` + parser: parser, + settings: settings, + }), + test({ + code: ` import { MyNamespace } from "./${source}" MyNamespace.NSModule.NSModuleFunction() `, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - ], - - invalid: [ - test({ - code: `import { MissingType } from "./${source}"`, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - errors: [{ - message: `MissingType not found in './${source}'`, - type: 'Identifier', - }], - }), - test({ - code: `import { NotExported } from "./${source}"`, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - errors: [{ - message: `NotExported not found in './${source}'`, - type: 'Identifier', - }], - }), - ], - }); + parser: parser, + settings: settings, + }), + ); + + invalid.push( + test({ + code: `import { MissingType } from "./${source}"`, + parser: parser, + settings: settings, + errors: [{ + message: `MissingType not found in './${source}'`, + type: 'Identifier', + }], + }), + test({ + code: `import { NotExported } from "./${source}"`, + parser: parser, + settings: settings, + errors: [{ + message: `NotExported not found in './${source}'`, + type: 'Identifier', + }], + }), + ); }); }); }); diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js index c6b355ab88..faf096acec 100644 --- a/tests/src/rules/no-duplicates.js +++ b/tests/src/rules/no-duplicates.js @@ -446,6 +446,13 @@ context('TypeScript', function() { code: "import type x from './foo'; import type {y} from './foo'", ...parserConfig, }), + test({ + code: ` + import type {} from './module'; + import {} from './module2'; + `, + ...parserConfig, + }), ], invalid: [ test({ diff --git a/tests/src/rules/no-extraneous-dependencies.js b/tests/src/rules/no-extraneous-dependencies.js index 7a11074684..370cce7e39 100644 --- a/tests/src/rules/no-extraneous-dependencies.js +++ b/tests/src/rules/no-extraneous-dependencies.js @@ -160,7 +160,10 @@ ruleTester.run('no-extraneous-dependencies', rule, { }), test({ - code: 'import "alias/esm-package/esm-module";', + code: ` + import "alias/esm-package/esm-module"; + import 'expose-loader?exposes[]=$&exposes[]=jQuery!jquery'; + `, settings: { 'import/resolver': 'webpack' }, }), ], diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js index 7f783624b4..8fb2b2604c 100644 --- a/utils/moduleVisitor.js +++ b/utils/moduleVisitor.js @@ -37,7 +37,7 @@ exports.default = function visitModules(visitor, options) { // for esmodule dynamic `import()` calls function checkImportCall(node) { let modulePath; - // refs https://github.com/estree/estree/blob/master/es2020.md#importexpression + // refs https://github.com/estree/estree/blob/HEAD/es2020.md#importexpression if (node.type === 'ImportExpression') { modulePath = node.source; } else if (node.type === 'CallExpression') {