diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c14fd348..84b1b4aa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange - [Tests] `no-nodejs-modules`: add tests for node protocol URL ([#2367], thanks [@sosukesuzuki]) - [Tests] `default`, `no-anonymous-default-export`, `no-mutable-exports`, `no-named-as-default-member`, `no-named-as-default`: add tests for arbitrary module namespace names ([#2358], thanks [@sosukesuzuki]) - [Docs] [`no-unresolved`]: Fix RegExp escaping in readme ([#2332], thanks [@stephtr]) +- [Refactor] `namespace`: try to improve performance ([#2340], thanks [@ljharb]) ## [2.25.4] - 2022-01-02 @@ -1255,6 +1256,7 @@ 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 +[#2340]: https://github.com/import-js/eslint-plugin-import/issues/2340 [#2255]: https://github.com/import-js/eslint-plugin-import/issues/2255 [#2210]: https://github.com/import-js/eslint-plugin-import/issues/2210 [#2201]: https://github.com/import-js/eslint-plugin-import/issues/2201 diff --git a/src/rules/namespace.js b/src/rules/namespace.js index 8a7099df6..405c415ce 100644 --- a/src/rules/namespace.js +++ b/src/rules/namespace.js @@ -3,6 +3,44 @@ import Exports from '../ExportMap'; import importDeclaration from '../importDeclaration'; import docsUrl from '../docsUrl'; +function processBodyStatement(context, namespaces, declaration) { + if (declaration.type !== 'ImportDeclaration') return; + + if (declaration.specifiers.length === 0) return; + + const imports = Exports.get(declaration.source.value, context); + if (imports == null) return null; + + if (imports.errors.length > 0) { + imports.reportErrors(context, declaration); + return; + } + + declaration.specifiers.forEach((specifier) => { + switch (specifier.type) { + case 'ImportNamespaceSpecifier': + if (!imports.size) { + context.report( + specifier, + `No exported names found in module '${declaration.source.value}'.`, + ); + } + namespaces.set(specifier.local.name, imports); + break; + case 'ImportDefaultSpecifier': + case 'ImportSpecifier': { + const meta = imports.get( + // default to 'default' for default https://i.imgur.com/nj6qAWy.jpg + specifier.imported ? (specifier.imported.name || specifier.imported.value) : 'default', + ); + if (!meta || !meta.namespace) { break; } + namespaces.set(specifier.local.name, meta.namespace); + break; + } + } + }); +} + module.exports = { meta: { type: 'problem', @@ -41,44 +79,7 @@ module.exports = { return { // pick up all imports at body entry time, to properly respect hoisting Program({ body }) { - function processBodyStatement(declaration) { - if (declaration.type !== 'ImportDeclaration') return; - - if (declaration.specifiers.length === 0) return; - - const imports = Exports.get(declaration.source.value, context); - if (imports == null) return null; - - if (imports.errors.length) { - imports.reportErrors(context, declaration); - return; - } - - for (const specifier of declaration.specifiers) { - switch (specifier.type) { - case 'ImportNamespaceSpecifier': - if (!imports.size) { - context.report( - specifier, - `No exported names found in module '${declaration.source.value}'.`, - ); - } - namespaces.set(specifier.local.name, imports); - break; - case 'ImportDefaultSpecifier': - case 'ImportSpecifier': { - const meta = imports.get( - // default to 'default' for default https://i.imgur.com/nj6qAWy.jpg - specifier.imported ? (specifier.imported.name || specifier.imported.value) : 'default', - ); - if (!meta || !meta.namespace) { break; } - namespaces.set(specifier.local.name, meta.namespace); - break; - } - } - } - } - body.forEach(processBodyStatement); + body.forEach(x => processBodyStatement(context, namespaces, x)); }, // same as above, but does not add names to local map @@ -120,7 +121,6 @@ module.exports = { const namepath = [dereference.object.name]; // while property is namespace and parent is member expression, keep validating while (namespace instanceof Exports && dereference.type === 'MemberExpression') { - if (dereference.computed) { if (!allowComputed) { context.report( @@ -147,7 +147,6 @@ module.exports = { namespace = exported.namespace; dereference = dereference.parent; } - }, VariableDeclarator({ id, init }) {