From 12bbfca747be9d88db32ff6d1659701cd8ed7fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Fermann?= Date: Tue, 16 Apr 2019 18:28:12 +0200 Subject: [PATCH 01/21] [fix] `no-unused-modules`: make appveyor tests passing Fixes #1317. --- src/rules/no-unused-modules.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js index 552004b6d..f80be0a6e 100644 --- a/src/rules/no-unused-modules.js +++ b/src/rules/no-unused-modules.js @@ -462,7 +462,7 @@ module.exports = { // support for export { value } from 'module' if (astNode.type === EXPORT_NAMED_DECLARATION) { if (astNode.source) { - resolvedPath = resolve(astNode.source.value, context) + resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context) astNode.specifiers.forEach(specifier => { let name if (specifier.exported.name === DEFAULT) { @@ -476,12 +476,12 @@ module.exports = { } if (astNode.type === EXPORT_ALL_DECLARATION) { - resolvedPath = resolve(astNode.source.value, context) + resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context) newExportAll.add(resolvedPath) } if (astNode.type === IMPORT_DECLARATION) { - resolvedPath = resolve(astNode.source.value, context) + resolvedPath = resolve(astNode.source.raw.replace(/('|")/g, ''), context) if (!resolvedPath) { return } From 174afbbffa9127db1728dae544fc26afb94eaf28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Fermann?= Date: Sun, 21 Apr 2019 21:37:52 +0200 Subject: [PATCH 02/21] [fix] `no-unused-modules`: make `import { name as otherName }` work --- src/rules/no-unused-modules.js | 2 +- tests/src/rules/no-unused-modules.js | 30 +++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js index f80be0a6e..d91411bf2 100644 --- a/src/rules/no-unused-modules.js +++ b/src/rules/no-unused-modules.js @@ -503,7 +503,7 @@ module.exports = { specifier.type === IMPORT_NAMESPACE_SPECIFIER) { return } - newImports.set(specifier.local.name, resolvedPath) + newImports.set(specifier.imported.name, resolvedPath) }) } }) diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js index 7b11ee6d0..fa4b59b30 100644 --- a/tests/src/rules/no-unused-modules.js +++ b/tests/src/rules/no-unused-modules.js @@ -254,6 +254,34 @@ ruleTester.run('no-unused-modules', rule, { ], }) +// add renamed named import for file with named export +ruleTester.run('no-unused-modules', rule, { + valid: [ + test({ options: unusedExportsOptions, + code: `import { g as g1 } from '${testFilePath('./no-unused-modules/file-g.js')}'; import eslint from 'eslint'`, + filename: testFilePath('./no-unused-modules/file-0.js')}), + test({ options: unusedExportsOptions, + code: 'export const g = 2', + filename: testFilePath('./no-unused-modules/file-g.js')}), + ], + invalid: [], +}) + +// add different renamed named import for file with named export +ruleTester.run('no-unused-modules', rule, { + valid: [ + test({ options: unusedExportsOptions, + code: `import { g1 as g } from '${testFilePath('./no-unused-modules/file-g.js')}'`, + filename: testFilePath('./no-unused-modules/file-0.js')}), + ], + invalid: [ + test({ options: unusedExportsOptions, + code: 'export const g = 2', + filename: testFilePath('./no-unused-modules/file-g.js'), + errors: [error(`exported declaration 'g' not used within other modules`)]}), + ], +}) + // remove default import for file with default export ruleTester.run('no-unused-modules', rule, { valid: [ @@ -556,7 +584,7 @@ describe('do not report missing export for ignored file', () => { test({ options: [{ src: [testFilePath('./no-unused-modules/**/*.js')], ignoreExports: [testFilePath('./no-unused-modules/*ignored*.js')], - missingExports: true + missingExports: true, }], code: 'export const test = true', filename: testFilePath('./no-unused-modules/file-ignored-a.js')}), From 1db357eaa22d936e4211d1b00d5d4b31ea6659f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Fermann?= Date: Tue, 23 Apr 2019 19:54:46 +0200 Subject: [PATCH 03/21] [fix] `no-unused-modules`: make `import { name as otherName }` work --- src/ExportMap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ExportMap.js b/src/ExportMap.js index b533946fa..8513e3d39 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -405,7 +405,7 @@ ExportMap.parse = function (path, content, context) { importedSpecifiers.add(specifier.type) } if (specifier.type === 'ImportSpecifier') { - importedSpecifiers.add(specifier.local.name) + importedSpecifiers.add(specifier.imported.name) } }) } From fbe5c30cf85e4a2c9fd9e8d29a12903c46a86b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Fermann?= Date: Wed, 24 Apr 2019 20:19:24 +0200 Subject: [PATCH 04/21] [fix] `no-unused-modules`: make `import { name as otherName }` work --- tests/files/no-unused-modules/file-h.js | 4 +++- tests/files/no-unused-modules/file-p.js | 1 + tests/src/rules/no-unused-modules.js | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 tests/files/no-unused-modules/file-p.js diff --git a/tests/files/no-unused-modules/file-h.js b/tests/files/no-unused-modules/file-h.js index b38d70e54..60b542e17 100644 --- a/tests/files/no-unused-modules/file-h.js +++ b/tests/files/no-unused-modules/file-h.js @@ -4,4 +4,6 @@ function h2() { return 3 } -export { h1, h2 } +const h3 = true + +export { h1, h2, h3 } diff --git a/tests/files/no-unused-modules/file-p.js b/tests/files/no-unused-modules/file-p.js new file mode 100644 index 000000000..60f3fbae4 --- /dev/null +++ b/tests/files/no-unused-modules/file-p.js @@ -0,0 +1 @@ +import { h3 as h0 } from './file-h' \ No newline at end of file diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js index fa4b59b30..8069479ae 100644 --- a/tests/src/rules/no-unused-modules.js +++ b/tests/src/rules/no-unused-modules.js @@ -118,7 +118,7 @@ ruleTester.run('no-unused-modules', rule, { filename: testFilePath('./no-unused-modules/file-g.js'), errors: [error(`exported declaration 'g' not used within other modules`)]}), test({ options: unusedExportsOptions, - code: 'const h1 = 3; function h2() { return 3 }; export { h1, h2 }', + code: 'const h1 = 3; function h2() { return 3 }; const h3 = true; export { h1, h2, h3 }', filename: testFilePath('./no-unused-modules/file-h.js'), errors: [error(`exported declaration 'h1' not used within other modules`)]}), test({ options: unusedExportsOptions, From 4620185d0aa93da9675afb73ec713f5b1c821051 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Wed, 24 Apr 2019 19:18:46 -0700 Subject: [PATCH 05/21] [fix] `named`: ignore Flow import typeof and export type --- CHANGELOG.md | 4 ++++ docs/rules/named.md | 2 +- src/rules/named.js | 9 ++++++--- tests/src/rules/named.js | 32 ++++++++++++++++++++++++++++++-- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index adc7faddf..70287d855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel ## [Unreleased] +- [`named`]: ignore Flow `typeof` imports and `type` exports ([#1345], thanks [@loganfsmyth]) + ## [2.17.2] - 2019-04-16 ### Fixed @@ -553,6 +555,7 @@ for info on changes for earlier releases. [`memo-parser`]: ./memo-parser/README.md +[#1345]: https://github.com/benmosher/eslint-plugin-import/pull/1345 [#1331]: https://github.com/benmosher/eslint-plugin-import/pull/1331 [#1330]: https://github.com/benmosher/eslint-plugin-import/pull/1330 [#1320]: https://github.com/benmosher/eslint-plugin-import/pull/1320 @@ -887,3 +890,4 @@ for info on changes for earlier releases. [@bradzacher]: https://github.com/bradzacher [@feychenie]: https://github.com/feychenie [@kiwka]: https://github.com/kiwka +[@loganfsmyth]: https://github.com/loganfsmyth diff --git a/docs/rules/named.md b/docs/rules/named.md index 0830af5e4..01ccb14ae 100644 --- a/docs/rules/named.md +++ b/docs/rules/named.md @@ -8,7 +8,7 @@ Note: for packages, the plugin will find exported names from [`jsnext:main`], if present in `package.json`. Redux's npm module includes this key, and thereby is lintable, for example. -A module path that is [ignored] or not [unambiguously an ES module] will not be reported when imported. Note that type imports, as used by [Flow], are always ignored. +A module path that is [ignored] or not [unambiguously an ES module] will not be reported when imported. Note that type imports and exports, as used by [Flow], are always ignored. [ignored]: ../../README.md#importignore [unambiguously an ES module]: https://github.com/bmeck/UnambiguousJavaScriptGrammar diff --git a/src/rules/named.js b/src/rules/named.js index b1f261f32..cc9199d48 100644 --- a/src/rules/named.js +++ b/src/rules/named.js @@ -12,8 +12,11 @@ module.exports = { create: function (context) { function checkSpecifiers(key, type, node) { - // ignore local exports and type imports - if (node.source == null || node.importKind === 'type') return + // ignore local exports and type imports/exports + if (node.source == null || node.importKind === 'type' || + node.importKind === 'typeof' || node.exportKind === 'type') { + return + } if (!node.specifiers .some(function (im) { return im.type === type })) { @@ -32,7 +35,7 @@ module.exports = { if (im.type !== type) return // ignore type imports - if (im.importKind === 'type') return + if (im.importKind === 'type' || im.importKind === 'typeof') return const deepLookup = imports.hasDeep(im[key].name) diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js index a3f55b35e..922914f90 100644 --- a/tests/src/rules/named.js +++ b/tests/src/rules/named.js @@ -70,17 +70,45 @@ ruleTester.run('named', rule, { test({ code: 'import { deepProp } from "./named-exports"' }), test({ code: 'import { deepSparseElement } from "./named-exports"' }), - // should ignore imported flow types, even if they don’t exist + // should ignore imported/exported flow types, even if they don’t exist test({ code: 'import type { MissingType } from "./flowtypes"', parser: 'babel-eslint', }), + test({ + code: 'import typeof { MissingType } from "./flowtypes"', + parser: 'babel-eslint', + }), test({ code: 'import type { MyOpaqueType } from "./flowtypes"', parser: 'babel-eslint', }), test({ - code: 'import { type MyOpaqueType, MyClass } from "./flowtypes"', + code: 'import typeof { MyOpaqueType } from "./flowtypes"', + parser: 'babel-eslint', + }), + test({ + code: 'import { type MyOpaqueType, MyClass } from "./flowtypes"', + parser: 'babel-eslint', + }), + test({ + code: 'import { typeof MyOpaqueType, MyClass } from "./flowtypes"', + parser: 'babel-eslint', + }), + test({ + code: 'import typeof MissingType from "./flowtypes"', + parser: 'babel-eslint', + }), + test({ + code: 'import typeof * as MissingType from "./flowtypes"', + parser: 'babel-eslint', + }), + test({ + code: 'export type { MissingType } from "./flowtypes"', + parser: 'babel-eslint', + }), + test({ + code: 'export type { MyOpaqueType } from "./flowtypes"', parser: 'babel-eslint', }), From bb686defa4199d5c1f77980b165907b9d3c0971b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Fermann?= Date: Sat, 27 Apr 2019 11:59:30 +0200 Subject: [PATCH 06/21] [fix] `no-unused-modules`: don't crash when lint file outside src-folder --- src/rules/no-unused-modules.js | 8 ++++++++ tests/src/rules/no-unused-modules.js | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js index d91411bf2..3d59e850e 100644 --- a/src/rules/no-unused-modules.js +++ b/src/rules/no-unused-modules.js @@ -302,6 +302,14 @@ module.exports = { return } + // refresh list of source files + const srcFiles = resolveFiles(getSrc(src), ignoreExports) + + // make sure file to be linted is included in source files + if (!srcFiles.has(file)) { + return + } + exports = exportList.get(file) // special case: export * from diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js index 8069479ae..c9e7fde15 100644 --- a/tests/src/rules/no-unused-modules.js +++ b/tests/src/rules/no-unused-modules.js @@ -592,3 +592,13 @@ describe('do not report missing export for ignored file', () => { invalid: [], }) }) + +// lint file not available in `src` +ruleTester.run('no-unused-modules', rule, { + valid: [ + test({ options: unusedExportsOptions, + code: `export const jsxFoo = 'foo'; export const jsxBar = 'bar'`, + filename: testFilePath('../jsx/named.jsx')}), + ], + invalid: [], +}) \ No newline at end of file From 7c13a4f781a02d35c37ce30f7759d85b4d40afc3 Mon Sep 17 00:00:00 2001 From: golopot Date: Sun, 12 May 2019 23:29:44 +0800 Subject: [PATCH 07/21] [Docs]: add missing `no-unused-modules` in README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3e60280a8..7369367bd 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a * Forbid a module from importing a module with a dependency path back to itself ([`no-cycle`]) * Prevent unnecessary path segments in import and require statements ([`no-useless-path-segments`]) * Forbid importing modules from parent directories ([`no-relative-parent-imports`]) +* Forbid modules without any export, and exports not imported by any modules. ([`no-unused-modules`]) [`no-unresolved`]: ./docs/rules/no-unresolved.md [`named`]: ./docs/rules/named.md @@ -41,6 +42,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a [`no-cycle`]: ./docs/rules/no-cycle.md [`no-useless-path-segments`]: ./docs/rules/no-useless-path-segments.md [`no-relative-parent-imports`]: ./docs/rules/no-relative-parent-imports.md +[`no-unused-modules`]: ./docs/rules/no-unused-modules.md ### Helpful warnings From 2f85fbea4c4eb498f8fcd7c797690cac0ba725b8 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 1 May 2019 15:15:42 -0700 Subject: [PATCH 08/21] [Docs] `no-unused-modules`: Indicates usage, plugin defaults to no-op, and add description to main README.md Fixes #1351 --- README.md | 2 ++ docs/rules/no-unused-modules.md | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7369367bd..ddc95d4f8 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a * Report imported names marked with `@deprecated` documentation tag ([`no-deprecated`]) * Forbid the use of extraneous packages ([`no-extraneous-dependencies`]) * Forbid the use of mutable exports with `var` or `let`. ([`no-mutable-exports`]) +* Report modules without exports, or exports without matching import in another module ([`no-unused-modules`]) [`export`]: ./docs/rules/export.md [`no-named-as-default`]: ./docs/rules/no-named-as-default.md @@ -60,6 +61,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a [`no-deprecated`]: ./docs/rules/no-deprecated.md [`no-extraneous-dependencies`]: ./docs/rules/no-extraneous-dependencies.md [`no-mutable-exports`]: ./docs/rules/no-mutable-exports.md +[`no-unused-modules`]: ./docs/rules/no-unused-modules.md ### Module systems diff --git a/docs/rules/no-unused-modules.md b/docs/rules/no-unused-modules.md index 96d689123..32db6465f 100644 --- a/docs/rules/no-unused-modules.md +++ b/docs/rules/no-unused-modules.md @@ -8,15 +8,26 @@ Note: dynamic imports are currently not supported. ## Rule Details +### Usage + +In order for this plugin to work, one of the options `missingExports` or `unusedExports` must be enabled (see "Options" section below). In the future, these options will be enabled by default (see https://github.com/benmosher/eslint-plugin-import/issues/1324) + +Example: +``` +"rules: { + ...otherRules, + "import/no-unused-modules": [1, {"unusedExports": true}] +} +``` ### Options This rule takes the following option: +- **`missingExports`**: if `true`, files without any exports are reported (defaults to `false`) +- **`unusedExports`**: if `true`, exports without any static usage within other modules are reported (defaults to `false`) - `src`: an array with files/paths to be analyzed. It only applies to unused exports. Defaults to `process.cwd()`, if not provided - `ignoreExports`: an array with files/paths for which unused exports will not be reported (e.g module entry points in a published package) -- `missingExports`: if `true`, files without any exports are reported -- `unusedExports`: if `true`, exports without any static usage within other modules are reported. ### Example for missing exports From 1edbbd03ec636469328ad59da922ed7edc8cd36d Mon Sep 17 00:00:00 2001 From: Charles Suh Date: Sun, 5 May 2019 16:47:41 -0700 Subject: [PATCH 09/21] [Fix] `no-common-js`: Also throw an error when assigning --- src/rules/no-commonjs.js | 1 + tests/src/rules/no-commonjs.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/rules/no-commonjs.js b/src/rules/no-commonjs.js index b6f11a7f0..261654bbf 100644 --- a/src/rules/no-commonjs.js +++ b/src/rules/no-commonjs.js @@ -91,6 +91,7 @@ module.exports = { if ( call.parent.type !== 'ExpressionStatement' && call.parent.type !== 'VariableDeclarator' + && call.parent.type !== 'AssignmentExpression' ) return if (call.callee.type !== 'Identifier') return diff --git a/tests/src/rules/no-commonjs.js b/tests/src/rules/no-commonjs.js index 72d5bfb19..c8155938b 100644 --- a/tests/src/rules/no-commonjs.js +++ b/tests/src/rules/no-commonjs.js @@ -60,6 +60,7 @@ ruleTester.run('no-commonjs', require('rules/no-commonjs'), { // imports { code: 'var x = require("x")', errors: [ { message: IMPORT_MESSAGE }] }, + { code: 'x = require("x")', errors: [ { message: IMPORT_MESSAGE }] }, { code: 'require("x")', errors: [ { message: IMPORT_MESSAGE }] }, // exports From aa290bbd5114332f4479011f94c18c03dc7d2fe6 Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Sat, 11 May 2019 16:32:00 -0700 Subject: [PATCH 10/21] Improve support for Typescript declare structures --- src/ExportMap.js | 15 ++ tests/files/typescript-declare.d.ts | 33 ++++ tests/files/typescript-export-assign.d.ts | 39 +++++ tests/src/rules/named.js | 186 +++++++++++----------- utils/unambiguous.js | 4 +- 5 files changed, 183 insertions(+), 94 deletions(-) create mode 100644 tests/files/typescript-declare.d.ts create mode 100644 tests/files/typescript-export-assign.d.ts diff --git a/src/ExportMap.js b/src/ExportMap.js index 8513e3d39..584cc2e0f 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -464,6 +464,7 @@ ExportMap.parse = function (path, content, context) { case 'ClassDeclaration': case 'TypeAlias': // flowtype with babel-eslint parser case 'InterfaceDeclaration': + case 'TSDeclareFunction': case 'TSEnumDeclaration': case 'TSTypeAliasDeclaration': case 'TSInterfaceDeclaration': @@ -509,6 +510,20 @@ ExportMap.parse = function (path, content, context) { m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) }) }) } + + // This doesn't declare anything, but changes what's being exported. + if (n.type === 'TSExportAssignment') { + const d = ast.body.find( + b => b.type === 'TSModuleDeclaration' && b.id.name === n.expression.name + ) + if (d && d.body && d.body.body) { + d.body.body.forEach(b => { + // Export-assignment exports all members in the namespace, explicitly exported or not. + const s = b.type === 'ExportNamedDeclaration' ? b.declaration : b + m.namespace.set(s.id.name, captureDoc(source, docStyleParsers, b)) + }) + } + } }) return m diff --git a/tests/files/typescript-declare.d.ts b/tests/files/typescript-declare.d.ts new file mode 100644 index 000000000..5d526b85b --- /dev/null +++ b/tests/files/typescript-declare.d.ts @@ -0,0 +1,33 @@ +export declare type MyType = string +export declare enum MyEnum { + Foo, + Bar, + Baz +} +export declare interface Foo { + native: string | number + typedef: MyType + enum: MyEnum +} + +export declare abstract class Bar { + abstract foo(): Foo + + method(); +} + +export declare function getFoo() : MyType; + +export declare module MyModule { + export function ModuleFunction(); +} + +export declare namespace MyNamespace { + export function NamespaceFunction(); + + export module NSModule { + export function NSModuleFunction(); + } +} + +interface NotExported {} diff --git a/tests/files/typescript-export-assign.d.ts b/tests/files/typescript-export-assign.d.ts new file mode 100644 index 000000000..7a3392ee0 --- /dev/null +++ b/tests/files/typescript-export-assign.d.ts @@ -0,0 +1,39 @@ +export = AssignedNamespace; + +declare namespace AssignedNamespace { + type MyType = string + enum MyEnum { + Foo, + Bar, + Baz + } + + interface Foo { + native: string | number + typedef: MyType + enum: MyEnum + } + + abstract class Bar { + abstract foo(): Foo + + method(); + } + + export function getFoo() : MyType; + + export module MyModule { + export function ModuleFunction(); + } + + export namespace MyNamespace { + export function NamespaceFunction(); + + export module NSModule { + export function NSModuleFunction(); + } + } + + // Export-assignment exports all members in the namespace, explicitly exported or not. + // interface NotExported {} +} diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js index 922914f90..8d8bd41c1 100644 --- a/tests/src/rules/named.js +++ b/tests/src/rules/named.js @@ -292,98 +292,100 @@ context('Typescript', function () { } parsers.forEach((parser) => { - ruleTester.run('named', rule, { - valid: [ - test({ - code: 'import { MyType } from "./typescript"', - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: 'import { Foo } from "./typescript"', - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: 'import { Bar } from "./typescript"', - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: 'import { getFoo } from "./typescript"', - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: 'import { MyEnum } from "./typescript"', - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: ` - import { MyModule } from "./typescript" - MyModule.ModuleFunction() - `, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - test({ - code: ` - import { MyNamespace } from "./typescript" - MyNamespace.NSModule.NSModuleFunction() - `, - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - }), - ], - - invalid: [ - test({ - code: 'import { MissingType } from "./typescript"', - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - errors: [{ - message: "MissingType not found in './typescript'", - type: 'Identifier', - }], - }), - test({ - code: 'import { NotExported } from "./typescript"', - parser: parser, - settings: { - 'import/parsers': { [parser]: ['.ts'] }, - 'import/resolver': { 'eslint-import-resolver-typescript': true }, - }, - errors: [{ - message: "NotExported not found in './typescript'", - type: 'Identifier', - }], - }), - ], + ['typescript', 'typescript-declare', 'typescript-export-assign'].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: ` + import { MyModule } from "./${source}" + MyModule.ModuleFunction() + `, + parser: parser, + settings: { + 'import/parsers': { [parser]: ['.ts'] }, + 'import/resolver': { 'eslint-import-resolver-typescript': true }, + }, + }), + 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', + }], + }), + ], + }) }) }) }) diff --git a/utils/unambiguous.js b/utils/unambiguous.js index a8e842cac..390ad27b6 100644 --- a/utils/unambiguous.js +++ b/utils/unambiguous.js @@ -2,7 +2,7 @@ exports.__esModule = true -const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*]))/m +const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))/m /** * detect possible imports/exports without a full parse. * @@ -18,7 +18,7 @@ exports.test = function isMaybeUnambiguousModule(content) { } // future-/Babel-proof at the expense of being a little loose -const unambiguousNodeType = /^(Exp|Imp)ort.*Declaration$/ +const unambiguousNodeType = /^(((Exp|Imp)ort.*Declaration)|TSExportAssignment)$/ /** * Given an AST, return true if the AST unambiguously represents a module. From 288cedfce0b7fdabcdeb910ff4d4cc1ffe90b385 Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Sun, 12 May 2019 09:39:04 -0700 Subject: [PATCH 11/21] Make groups non-capturing. Co-Authored-By: Jordan Harband --- utils/unambiguous.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/unambiguous.js b/utils/unambiguous.js index 390ad27b6..1dae1d616 100644 --- a/utils/unambiguous.js +++ b/utils/unambiguous.js @@ -18,7 +18,7 @@ exports.test = function isMaybeUnambiguousModule(content) { } // future-/Babel-proof at the expense of being a little loose -const unambiguousNodeType = /^(((Exp|Imp)ort.*Declaration)|TSExportAssignment)$/ +const unambiguousNodeType = /^(?:(?:Exp|Imp)ort.*Declaration|TSExportAssignment)$/ /** * Given an AST, return true if the AST unambiguously represents a module. From 67b1e955f7b17a645d68695d6f1c317cd6100c70 Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Sun, 12 May 2019 10:02:50 -0700 Subject: [PATCH 12/21] Support older typescript parsers --- src/ExportMap.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/ExportMap.js b/src/ExportMap.js index 584cc2e0f..c563c94ac 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -464,6 +464,7 @@ ExportMap.parse = function (path, content, context) { case 'ClassDeclaration': case 'TypeAlias': // flowtype with babel-eslint parser case 'InterfaceDeclaration': + case 'DeclareFunction': case 'TSDeclareFunction': case 'TSEnumDeclaration': case 'TSTypeAliasDeclaration': @@ -513,14 +514,20 @@ ExportMap.parse = function (path, content, context) { // This doesn't declare anything, but changes what's being exported. if (n.type === 'TSExportAssignment') { - const d = ast.body.find( - b => b.type === 'TSModuleDeclaration' && b.id.name === n.expression.name + const md = ast.body.find( + (b) => b.type === 'TSModuleDeclaration' && b.id.name === n.expression.name ) - if (d && d.body && d.body.body) { - d.body.body.forEach(b => { + if (md && md.body && md.body.body) { + md.body.body.forEach((b) => { // Export-assignment exports all members in the namespace, explicitly exported or not. const s = b.type === 'ExportNamedDeclaration' ? b.declaration : b - m.namespace.set(s.id.name, captureDoc(source, docStyleParsers, b)) + if (s.type === 'VariableDeclaration') { + s.declarations.forEach((d) => + recursivePatternCapture(d.id, + id => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n)))) + } else { + m.namespace.set(s.id.name, captureDoc(source, docStyleParsers, b)) + } }) } } From d1e4455d01d41a386896733413f631c070c37da1 Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Sun, 12 May 2019 19:42:37 -0700 Subject: [PATCH 13/21] Verbose variable names --- src/ExportMap.js | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/ExportMap.js b/src/ExportMap.js index c563c94ac..949df3f19 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -514,19 +514,27 @@ ExportMap.parse = function (path, content, context) { // This doesn't declare anything, but changes what's being exported. if (n.type === 'TSExportAssignment') { - const md = ast.body.find( - (b) => b.type === 'TSModuleDeclaration' && b.id.name === n.expression.name + const moduleDecl = ast.body.find((bodyNode) => + bodyNode.type === 'TSModuleDeclaration' && bodyNode.id.name === n.expression.name ) - if (md && md.body && md.body.body) { - md.body.body.forEach((b) => { + log(moduleDecl) + log(moduleDecl.body) + if (moduleDecl && moduleDecl.body && moduleDecl.body.body) { + moduleDecl.body.body.forEach((moduleBlockNode) => { // Export-assignment exports all members in the namespace, explicitly exported or not. - const s = b.type === 'ExportNamedDeclaration' ? b.declaration : b - if (s.type === 'VariableDeclaration') { - s.declarations.forEach((d) => - recursivePatternCapture(d.id, - id => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n)))) + const exportedDecl = moduleBlockNode.type === 'ExportNamedDeclaration' ? + moduleBlockNode.declaration : + moduleBlockNode + + if (exportedDecl.type === 'VariableDeclaration') { + exportedDecl.declarations.forEach((decl) => + recursivePatternCapture(decl.id,(id) => m.namespace.set( + id.name, captureDoc(source, docStyleParsers, decl, exportedDecl, moduleBlockNode)) + ) + ) } else { - m.namespace.set(s.id.name, captureDoc(source, docStyleParsers, b)) + m.namespace.set(exportedDecl.id.name, + captureDoc(source, docStyleParsers, moduleBlockNode)) } }) } From f66e0649601aae5ed16b29b67eb65c2695ad5b2a Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Sun, 12 May 2019 19:43:59 -0700 Subject: [PATCH 14/21] Remove log messages --- src/ExportMap.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ExportMap.js b/src/ExportMap.js index 949df3f19..fb242b564 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -517,8 +517,6 @@ ExportMap.parse = function (path, content, context) { const moduleDecl = ast.body.find((bodyNode) => bodyNode.type === 'TSModuleDeclaration' && bodyNode.id.name === n.expression.name ) - log(moduleDecl) - log(moduleDecl.body) if (moduleDecl && moduleDecl.body && moduleDecl.body.body) { moduleDecl.body.body.forEach((moduleBlockNode) => { // Export-assignment exports all members in the namespace, explicitly exported or not. From 7aa13d14ca0fe890a34f7addadee08606484d68f Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Mon, 13 May 2019 14:56:02 -0700 Subject: [PATCH 15/21] PR feedback Co-Authored-By: Jordan Harband --- src/ExportMap.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ExportMap.js b/src/ExportMap.js index fb242b564..dfc315b7d 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -527,7 +527,8 @@ ExportMap.parse = function (path, content, context) { if (exportedDecl.type === 'VariableDeclaration') { exportedDecl.declarations.forEach((decl) => recursivePatternCapture(decl.id,(id) => m.namespace.set( - id.name, captureDoc(source, docStyleParsers, decl, exportedDecl, moduleBlockNode)) + id.name, + captureDoc(source, docStyleParsers, decl, exportedDecl, moduleBlockNode)) ) ) } else { From b52bf3e16bf399c5cf0681c198a3b362e6e7484b Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Mon, 13 May 2019 14:56:12 -0700 Subject: [PATCH 16/21] PR feedback Co-Authored-By: Jordan Harband --- src/ExportMap.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ExportMap.js b/src/ExportMap.js index dfc315b7d..d49ab5560 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -532,7 +532,8 @@ ExportMap.parse = function (path, content, context) { ) ) } else { - m.namespace.set(exportedDecl.id.name, + m.namespace.set( + exportedDecl.id.name, captureDoc(source, docStyleParsers, moduleBlockNode)) } }) From 753c9dbf04cca2729bf693d99106b68c81119d41 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 14 May 2019 22:28:46 -0500 Subject: [PATCH 17/21] [refactor] fix eslint 6 compat by fixing imports --- .travis.yml | 8 ++++++- src/ExportMap.js | 2 +- src/rules/no-unused-modules.js | 41 +++++++++++++++++++++------------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index e8eaf9d96..441fc86dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ node_js: os: linux env: + - ESLINT_VERSION=^6.0.0-alpha - ESLINT_VERSION=5 - ESLINT_VERSION=4 - ESLINT_VERSION=3 @@ -49,12 +50,17 @@ matrix: exclude: - node_js: '4' env: ESLINT_VERSION=5 - + - node_js: '4' + env: ESLINT_VERSION=^6.0.0-alpha + - node_js: '6' + env: ESLINT_VERSION=^6.0.0-alpha + fast_finish: true allow_failures: # issues with typescript deps in this version intersection - node_js: '4' env: ESLINT_VERSION=4 + - env: ESLINT_VERSION=^6.0.0-alpha before_install: - 'nvm install-latest-npm' diff --git a/src/ExportMap.js b/src/ExportMap.js index 8513e3d39..243b885a7 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -4,7 +4,7 @@ import doctrine from 'doctrine' import debug from 'debug' -import SourceCode from 'eslint/lib/util/source-code' +import { SourceCode } from 'eslint' import parse from 'eslint-module-utils/parse' import resolve from 'eslint-module-utils/resolve' diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js index 3d59e850e..e168aea2e 100644 --- a/src/rules/no-unused-modules.js +++ b/src/rules/no-unused-modules.js @@ -1,5 +1,5 @@ /** - * @fileOverview Ensures that modules contain exports and/or all + * @fileOverview Ensures that modules contain exports and/or all * modules are consumed within other modules. * @author René Fermann */ @@ -9,19 +9,28 @@ import resolve from 'eslint-module-utils/resolve' import docsUrl from '../docsUrl' // eslint/lib/util/glob-util has been moved to eslint/lib/util/glob-utils with version 5.3 +// and has been moved to eslint/lib/cli-engine/file-enumerator in version 6 let listFilesToProcess try { - listFilesToProcess = require('eslint/lib/util/glob-utils').listFilesToProcess -} catch (err) { - listFilesToProcess = require('eslint/lib/util/glob-util').listFilesToProcess + var FileEnumerator = require('eslint/lib/cli-engine/file-enumerator').FileEnumerator + listFilesToProcess = function (src) { + var e = new FileEnumerator() + return Array.from(e.iterateFiles(src)) + } +} catch (e1) { + try { + listFilesToProcess = require('eslint/lib/util/glob-utils').listFilesToProcess + } catch (e2) { + listFilesToProcess = require('eslint/lib/util/glob-util').listFilesToProcess + } } const EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration' const EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration' const EXPORT_ALL_DECLARATION = 'ExportAllDeclaration' -const IMPORT_DECLARATION = 'ImportDeclaration' +const IMPORT_DECLARATION = 'ImportDeclaration' const IMPORT_NAMESPACE_SPECIFIER = 'ImportNamespaceSpecifier' -const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier' +const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier' const VARIABLE_DECLARATION = 'VariableDeclaration' const FUNCTION_DECLARATION = 'FunctionDeclaration' const DEFAULT = 'default' @@ -37,7 +46,7 @@ const isNodeModule = path => { /** * read all files matching the patterns in src and ignoreExports - * + * * return all files matching src pattern, which are not matching the ignoreExports pattern */ const resolveFiles = (src, ignoreExports) => { @@ -73,7 +82,7 @@ const prepareImportsAndExports = (srcFiles, context) => { currentExportAll.add(value().path) }) exportAll.set(file, currentExportAll) - + reexports.forEach((value, key) => { if (key === DEFAULT) { exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed: new Set() }) @@ -106,7 +115,7 @@ const prepareImportsAndExports = (srcFiles, context) => { imports.set(key, value.importedSpecifiers) }) importList.set(file, imports) - + // build up export list only, if file is not ignored if (ignoredFiles.has(file)) { return @@ -266,7 +275,7 @@ module.exports = { if (unusedExports && !preparationDone) { doPreparation(src, ignoreExports, context) } - + const file = context.getFilename() const checkExportPresence = node => { @@ -329,9 +338,9 @@ module.exports = { } const exportStatement = exports.get(exportedValue) - + const value = exportedValue === IMPORT_DEFAULT_SPECIFIER ? DEFAULT : exportedValue - + if (typeof exportStatement !== 'undefined'){ if (exportStatement.whereUsed.size < 1) { context.report( @@ -410,7 +419,7 @@ module.exports = { // preserve information about namespace imports let exportAll = exports.get(EXPORT_ALL_DECLARATION) let namespaceImports = exports.get(IMPORT_NAMESPACE_SPECIFIER) - + if (typeof namespaceImports === 'undefined') { namespaceImports = { whereUsed: new Set() } } @@ -434,13 +443,13 @@ module.exports = { if (typeof oldImportPaths === 'undefined') { oldImportPaths = new Map() } - + const oldNamespaceImports = new Set() const newNamespaceImports = new Set() const oldExportAll = new Set() const newExportAll = new Set() - + const oldDefaultImports = new Set() const newDefaultImports = new Set() @@ -493,7 +502,7 @@ module.exports = { if (!resolvedPath) { return } - + if (isNodeModule(resolvedPath)) { return } From c09c0ce09c2666d92b1dfbd1a022f155543d19dd Mon Sep 17 00:00:00 2001 From: Ken Gregory Date: Wed, 15 May 2019 17:49:38 -0400 Subject: [PATCH 18/21] Issue #1258 (docs) Document `env` option for `eslint-import-resolver-webpack` --- resolvers/webpack/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/resolvers/webpack/README.md b/resolvers/webpack/README.md index 711b663f2..a9869aec4 100644 --- a/resolvers/webpack/README.md +++ b/resolvers/webpack/README.md @@ -66,3 +66,16 @@ settings: - .js - .jsx ``` + +If your config relies on [environment variables](https://webpack.js.org/guides/environment-variables/), they can be specified using the `env` parameter. If your config is a function, it will be invoked with the value assigned to `env`: + +```yaml +--- +settings: + import/resolver: + webpack: + config: 'webpack.config.js' + env: + NODE_ENV: 'local' + production: true +``` From 557a3e21642454190b32d741e6cbe10420c4b126 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 23 May 2019 13:29:54 -0700 Subject: [PATCH 19/21] [Deps] update `resolve` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f8d46a1bd..bad7484cb 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "lodash": "^4.17.11", "minimatch": "^3.0.4", "read-pkg-up": "^2.0.0", - "resolve": "^1.10.0" + "resolve": "^1.11.0" }, "nyc": { "require": [ From caae65c57b309daac7c54bc5855bdf758d9c198e Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 23 May 2019 13:58:54 -0700 Subject: [PATCH 20/21] [Tests] eslint 2 does not have `linter.version` --- tests/src/core/getExports.js | 4 ++-- tests/src/rules/export.js | 5 +++-- tests/src/rules/named.js | 5 +++-- tests/src/utils.js | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/src/core/getExports.js b/tests/src/core/getExports.js index 6e0942612..78b5319bb 100644 --- a/tests/src/core/getExports.js +++ b/tests/src/core/getExports.js @@ -1,6 +1,6 @@ import { expect } from 'chai' import semver from 'semver' -import { linter } from 'eslint' +import eslintPkg from 'eslint/package.json' import ExportMap from '../../../src/ExportMap' import * as fs from 'fs' @@ -335,7 +335,7 @@ describe('ExportMap', function () { ['array form', { 'typescript-eslint-parser': ['.ts', '.tsx'] }], ] - if (semver.satisfies(linter.version, '>5.0.0')) { + if (semver.satisfies(eslintPkg.version, '>5.0.0')) { configs.push(['array form', { '@typescript-eslint/parser': ['.ts', '.tsx'] }]) } diff --git a/tests/src/rules/export.js b/tests/src/rules/export.js index 3aad5241e..6431c542c 100644 --- a/tests/src/rules/export.js +++ b/tests/src/rules/export.js @@ -1,6 +1,7 @@ import { test, SYNTAX_CASES } from '../utils' -import { RuleTester, linter } from 'eslint' +import { RuleTester } from 'eslint' +import eslintPkg from 'eslint/package.json' import semver from 'semver' var ruleTester = new RuleTester() @@ -113,7 +114,7 @@ context('Typescript', function () { // Typescript const parsers = ['typescript-eslint-parser'] - if (semver.satisfies(linter.version, '>5.0.0')) { + if (semver.satisfies(eslintPkg.version, '>5.0.0')) { parsers.push('@typescript-eslint/parser') } diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js index 8d8bd41c1..6592aa958 100644 --- a/tests/src/rules/named.js +++ b/tests/src/rules/named.js @@ -1,5 +1,6 @@ import { test, SYNTAX_CASES } from '../utils' -import { RuleTester, linter } from 'eslint' +import { RuleTester } from 'eslint' +import eslintPkg from 'eslint/package.json' import semver from 'semver' import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve' @@ -287,7 +288,7 @@ context('Typescript', function () { // Typescript const parsers = ['typescript-eslint-parser'] - if (semver.satisfies(linter.version, '>5.0.0')) { + if (semver.satisfies(eslintPkg.version, '>5.0.0')) { parsers.push('@typescript-eslint/parser') } diff --git a/tests/src/utils.js b/tests/src/utils.js index 4d4f42dc8..b416ec83d 100644 --- a/tests/src/utils.js +++ b/tests/src/utils.js @@ -1,5 +1,5 @@ import path from 'path' -import { linter } from 'eslint' +import eslintPkg from 'eslint/package.json' import semver from 'semver' // warms up the module cache. this import takes a while (>500ms) @@ -12,7 +12,7 @@ export function testFilePath(relativePath) { export const FILENAME = testFilePath('foo.js') export function testVersion(specifier, t) { - return semver.satisfies(linter.version, specifier) && test(t) + return semver.satisfies(eslintPkg.version, specifier) && test(t) } export function test(t) { From cf5573b5784a8b19c1a7c3e4003005dfaadc4375 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 24 May 2019 14:32:05 -0700 Subject: [PATCH 21/21] Bump to v2.17.3 --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70287d855..e9a08b114 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,22 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel ## [Unreleased] +## [2.17.3] - 2019-05-23 + +### Fixed +- [`no-common-js`]: Also throw an error when assigning ([#1354], thanks [@charlessuh]) +- [`no-unused-modules`]: don't crash when lint file outside src-folder ([#1347], thanks [@rfermann]) +- [`no-unused-modules`]: make `import { name as otherName }` work ([#1340], [#1342], thanks [@rfermann]) +- [`no-unused-modules`]: make appveyor tests passing ([#1333], thanks [@rfermann]) - [`named`]: ignore Flow `typeof` imports and `type` exports ([#1345], thanks [@loganfsmyth]) +- [refactor] fix eslint 6 compat by fixing imports (thank [@ljharb]) +- Improve support for Typescript declare structures ([#1356], thanks [@christophercurrie]) + +### Docs +- add missing `no-unused-modules` in README ([#1358], thanks [@golopot]) +- [`no-unused-modules`]: Indicates usage, plugin defaults to no-op, and add description to main README.md ([#1352], thanks [@johndevedu]) +[@christophercurrie]: https://github.com/christophercurrie +- Document `env` option for `eslint-import-resolver-webpack` ([#1363], thanks [@kgregory]) ## [2.17.2] - 2019-04-16 @@ -555,7 +570,16 @@ for info on changes for earlier releases. [`memo-parser`]: ./memo-parser/README.md +[#1363]: https://github.com/benmosher/eslint-plugin-import/pull/1363 +[#1358]: https://github.com/benmosher/eslint-plugin-import/pull/1358 +[#1356]: https://github.com/benmosher/eslint-plugin-import/pull/1356 +[#1354]: https://github.com/benmosher/eslint-plugin-import/pull/1354 +[#1352]: https://github.com/benmosher/eslint-plugin-import/pull/1352 +[#1347]: https://github.com/benmosher/eslint-plugin-import/pull/1347 [#1345]: https://github.com/benmosher/eslint-plugin-import/pull/1345 +[#1342]: https://github.com/benmosher/eslint-plugin-import/pull/1342 +[#1340]: https://github.com/benmosher/eslint-plugin-import/pull/1340 +[#1333]: https://github.com/benmosher/eslint-plugin-import/pull/1333 [#1331]: https://github.com/benmosher/eslint-plugin-import/pull/1331 [#1330]: https://github.com/benmosher/eslint-plugin-import/pull/1330 [#1320]: https://github.com/benmosher/eslint-plugin-import/pull/1320 @@ -891,3 +915,7 @@ for info on changes for earlier releases. [@feychenie]: https://github.com/feychenie [@kiwka]: https://github.com/kiwka [@loganfsmyth]: https://github.com/loganfsmyth +[@johndevedu]: https://github.com/johndevedu +[@charlessuh]: https://github.com/charlessuh +[@kgregory]: https://github.com/kgregory +[@christophercurrie]: https://github.com/christophercurrie diff --git a/package.json b/package.json index bad7484cb..99f729b3f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-import", - "version": "2.17.2", + "version": "2.17.3", "description": "Import with sanity.", "engines": { "node": ">=4"