From 366eeaf8ba87adf7c2e165b0a73406292c002ad9 Mon Sep 17 00:00:00 2001 From: Carlo Corradini Date: Tue, 11 Mar 2025 23:25:56 +0100 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20if=20file=20has=20no=20corresponding?= =?UTF-8?q?=20mapper=20function,=20apply=20all=20of=20them=E2=80=A6=20(#37?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/long-insects-tan.md | 5 ++ .size-limit.json | 2 +- package.json | 1 + src/index.ts | 91 +++++++++++++++------ tests/nearestTsconfig/.eslintrc.cjs | 10 +++ tests/nearestTsconfig/a/app/app.ts | 2 + tests/nearestTsconfig/a/b/app/app.ts | 2 + tests/nearestTsconfig/a/b/c/app/app.ts | 2 + tests/nearestTsconfig/a/b/c/components/c.ts | 1 + tests/nearestTsconfig/a/b/c/tsconfig.json | 9 ++ tests/nearestTsconfig/a/b/components/b.ts | 1 + tests/nearestTsconfig/a/b/tsconfig.json | 9 ++ tests/nearestTsconfig/a/components/a.ts | 1 + tests/nearestTsconfig/a/tsconfig.json | 9 ++ tests/nearestTsconfig/app/app.ts | 1 + tests/nearestTsconfig/components/root.ts | 1 + tests/nearestTsconfig/tsconfig.json | 9 ++ 17 files changed, 128 insertions(+), 28 deletions(-) create mode 100644 .changeset/long-insects-tan.md create mode 100644 tests/nearestTsconfig/.eslintrc.cjs create mode 100644 tests/nearestTsconfig/a/app/app.ts create mode 100644 tests/nearestTsconfig/a/b/app/app.ts create mode 100644 tests/nearestTsconfig/a/b/c/app/app.ts create mode 100644 tests/nearestTsconfig/a/b/c/components/c.ts create mode 100644 tests/nearestTsconfig/a/b/c/tsconfig.json create mode 100644 tests/nearestTsconfig/a/b/components/b.ts create mode 100644 tests/nearestTsconfig/a/b/tsconfig.json create mode 100644 tests/nearestTsconfig/a/components/a.ts create mode 100644 tests/nearestTsconfig/a/tsconfig.json create mode 100644 tests/nearestTsconfig/app/app.ts create mode 100644 tests/nearestTsconfig/components/root.ts create mode 100644 tests/nearestTsconfig/tsconfig.json diff --git a/.changeset/long-insects-tan.md b/.changeset/long-insects-tan.md new file mode 100644 index 00000000..4f341cdb --- /dev/null +++ b/.changeset/long-insects-tan.md @@ -0,0 +1,5 @@ +--- +'eslint-import-resolver-typescript': patch +--- + +fix: if file has no corresponding mapper function, apply all of them, starting with the nearest one. diff --git a/.size-limit.json b/.size-limit.json index 0c0657ad..648747e9 100644 --- a/.size-limit.json +++ b/.size-limit.json @@ -1,6 +1,6 @@ [ { "path": "./lib/index.js", - "limit": "3kB" + "limit": "3.1kB" } ] diff --git a/package.json b/package.json index c35a251a..cf2511e1 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "test:importXResolverV3": "cross-env ESLINT_USE_FLAT_CONFIG=true eslint --config=tests/importXResolverV3/eslint.config.js tests/importXResolverV3", "test:multipleEslintrcs": "eslint --ext ts,tsx tests/multipleEslintrcs", "test:multipleTsconfigs": "eslint --ext ts,tsx tests/multipleTsconfigs", + "test:nearestTsconfig": "eslint --ext ts,tsx tests/nearestTsconfig", "test:withJsExtension": "node tests/withJsExtension/test.js && eslint --ext ts,tsx tests/withJsExtension", "test:withJsconfig": "eslint --ext js tests/withJsconfig", "test:withPaths": "eslint --ext ts,tsx tests/withPaths", diff --git a/src/index.ts b/src/index.ts index 1287aefe..b774b3ce 100644 --- a/src/index.ts +++ b/src/index.ts @@ -112,6 +112,7 @@ let prevCwd: string let mappersCachedOptions: InternalResolverOptions let mappers: Array<{ + path: string files: Set mapperFn: NonNullable> }> = [] @@ -311,35 +312,50 @@ function getMappedPaths( paths = [resolved] } } else { - paths = [ - ...new Set( - mappers - .filter(({ files }) => files.has(file)) - .map(({ mapperFn }) => - mapperFn(source).map(item => [ - ...extensions.map(ext => `${item}${ext}`), - ...originalExtensions.map(ext => `${item}/index${ext}`), - ]), - ) - .flat(2) - .map(toNativePathSeparator), - ), - ].filter(mappedPath => { - try { - const stat = fs.statSync(mappedPath, { throwIfNoEntry: false }) - if (stat === undefined) return false - if (stat.isFile()) return true - - // Maybe this is a module dir? - if (stat.isDirectory()) { - return isModule(mappedPath) + // Filter mapper functions associated with file + let mapperFns: Array>> = + mappers + .filter(({ files }) => files.has(file)) + .map(({ mapperFn }) => mapperFn) + if (mapperFns.length === 0) { + // If empty, try all mapper functions, starting with the nearest one + mapperFns = mappers + .map(mapper => ({ + mapperFn: mapper.mapperFn, + counter: equalChars(path.dirname(file), path.dirname(mapper.path)), + })) + .sort( + (a, b) => + // Sort in descending order where the nearest one has the longest counter + b.counter - a.counter, + ) + .map(({ mapperFn }) => mapperFn) + } + paths = mapperFns + .map(mapperFn => + mapperFn(source).map(item => [ + ...extensions.map(ext => `${item}${ext}`), + ...originalExtensions.map(ext => `${item}/index${ext}`), + ]), + ) + .flat(2) + .map(toNativePathSeparator) + .filter(mappedPath => { + try { + const stat = fs.statSync(mappedPath, { throwIfNoEntry: false }) + if (stat === undefined) return false + if (stat.isFile()) return true + + // Maybe this is a module dir? + if (stat.isDirectory()) { + return isModule(mappedPath) + } + } catch { + return false } - } catch { - return false - } - return false - }) + return false + }) } if (retry && paths.length === 0) { @@ -487,6 +503,7 @@ function initMappers(options: InternalResolverOptions) { } return { + path: toNativePathSeparator(tsconfigResult.path), files: new Set(files.map(toNativePathSeparator)), mapperFn, } @@ -551,3 +568,23 @@ function toNativePathSeparator(p: string) { function isDefined(value: T | null | undefined): value is T { return value !== null && value !== undefined } + +/** + * Counts how many characters in strings `a` and `b` are exactly the same and in the same position. + * + * @param {string} a First string + * @param {string} b Second string + * @returns Number of matching characters + */ +function equalChars(a: string, b: string): number { + if (a.length === 0 || b.length === 0) { + return 0 + } + + let i = 0 + const length = Math.min(a.length, b.length) + while (i < length && a.charAt(i) === b.charAt(i)) { + i += 1 + } + return i +} diff --git a/tests/nearestTsconfig/.eslintrc.cjs b/tests/nearestTsconfig/.eslintrc.cjs new file mode 100644 index 00000000..285ee8d6 --- /dev/null +++ b/tests/nearestTsconfig/.eslintrc.cjs @@ -0,0 +1,10 @@ +const path = require('node:path') + +const project = [ + 'tsconfig.json', + 'a/tsconfig.json', + 'a/b/tsconfig.json', + 'a/b/c/tsconfig.json', +].map(tsconfig => path.resolve(__dirname, tsconfig)) + +module.exports = require('../baseEslintConfig.cjs')(project) diff --git a/tests/nearestTsconfig/a/app/app.ts b/tests/nearestTsconfig/a/app/app.ts new file mode 100644 index 00000000..9597f5bf --- /dev/null +++ b/tests/nearestTsconfig/a/app/app.ts @@ -0,0 +1,2 @@ +import 'components/a' +import 'components/root' diff --git a/tests/nearestTsconfig/a/b/app/app.ts b/tests/nearestTsconfig/a/b/app/app.ts new file mode 100644 index 00000000..61b335ec --- /dev/null +++ b/tests/nearestTsconfig/a/b/app/app.ts @@ -0,0 +1,2 @@ +import 'components/b' +import 'components/root' diff --git a/tests/nearestTsconfig/a/b/c/app/app.ts b/tests/nearestTsconfig/a/b/c/app/app.ts new file mode 100644 index 00000000..e49cf01e --- /dev/null +++ b/tests/nearestTsconfig/a/b/c/app/app.ts @@ -0,0 +1,2 @@ +import 'components/c' +import 'components/root' diff --git a/tests/nearestTsconfig/a/b/c/components/c.ts b/tests/nearestTsconfig/a/b/c/components/c.ts new file mode 100644 index 00000000..da4b0eda --- /dev/null +++ b/tests/nearestTsconfig/a/b/c/components/c.ts @@ -0,0 +1 @@ +export default 'c' diff --git a/tests/nearestTsconfig/a/b/c/tsconfig.json b/tests/nearestTsconfig/a/b/c/tsconfig.json new file mode 100644 index 00000000..6f4b6a28 --- /dev/null +++ b/tests/nearestTsconfig/a/b/c/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "components/*": ["../../../components/*", "./components/*"] + } + }, + "files": ["components/c.ts"] +} diff --git a/tests/nearestTsconfig/a/b/components/b.ts b/tests/nearestTsconfig/a/b/components/b.ts new file mode 100644 index 00000000..a3bb4904 --- /dev/null +++ b/tests/nearestTsconfig/a/b/components/b.ts @@ -0,0 +1 @@ +export default 'b' diff --git a/tests/nearestTsconfig/a/b/tsconfig.json b/tests/nearestTsconfig/a/b/tsconfig.json new file mode 100644 index 00000000..fedccddb --- /dev/null +++ b/tests/nearestTsconfig/a/b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "components/*": ["../../components/*", "./components/*"] + } + }, + "files": ["components/b.ts"] +} diff --git a/tests/nearestTsconfig/a/components/a.ts b/tests/nearestTsconfig/a/components/a.ts new file mode 100644 index 00000000..90bd54cd --- /dev/null +++ b/tests/nearestTsconfig/a/components/a.ts @@ -0,0 +1 @@ +export default 'a' diff --git a/tests/nearestTsconfig/a/tsconfig.json b/tests/nearestTsconfig/a/tsconfig.json new file mode 100644 index 00000000..c01728fe --- /dev/null +++ b/tests/nearestTsconfig/a/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "components/*": ["../components/*", "./components/*"] + } + }, + "files": ["components/a.ts"] +} diff --git a/tests/nearestTsconfig/app/app.ts b/tests/nearestTsconfig/app/app.ts new file mode 100644 index 00000000..60f1cde9 --- /dev/null +++ b/tests/nearestTsconfig/app/app.ts @@ -0,0 +1 @@ +import 'components/root' diff --git a/tests/nearestTsconfig/components/root.ts b/tests/nearestTsconfig/components/root.ts new file mode 100644 index 00000000..8c841b31 --- /dev/null +++ b/tests/nearestTsconfig/components/root.ts @@ -0,0 +1 @@ +export default 'root' diff --git a/tests/nearestTsconfig/tsconfig.json b/tests/nearestTsconfig/tsconfig.json new file mode 100644 index 00000000..21cf5788 --- /dev/null +++ b/tests/nearestTsconfig/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "components/*": ["./components/*"] + } + }, + "files": ["components/root.ts"] +} From 7d63ec77eb508529e65767ed5e22282c3d8a51ba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 11 Mar 2025 22:54:58 +0000 Subject: [PATCH 2/2] chore: release eslint-import-resolver-typescript (#373) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/long-insects-tan.md | 5 ----- CHANGELOG.md | 6 ++++++ package.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) delete mode 100644 .changeset/long-insects-tan.md diff --git a/.changeset/long-insects-tan.md b/.changeset/long-insects-tan.md deleted file mode 100644 index 4f341cdb..00000000 --- a/.changeset/long-insects-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'eslint-import-resolver-typescript': patch ---- - -fix: if file has no corresponding mapper function, apply all of them, starting with the nearest one. diff --git a/CHANGELOG.md b/CHANGELOG.md index 70319074..f2183de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 3.8.5 + +### Patch Changes + +- [#372](https://github.com/import-js/eslint-import-resolver-typescript/pull/372) [`366eeaf`](https://github.com/import-js/eslint-import-resolver-typescript/commit/366eeaf8ba87adf7c2e165b0a73406292c002ad9) Thanks [@carlocorradini](https://github.com/carlocorradini)! - fix: if file has no corresponding mapper function, apply all of them, starting with the nearest one. + ## 3.8.4 ### Patch Changes diff --git a/package.json b/package.json index cf2511e1..86e53743 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-import-resolver-typescript", - "version": "3.8.4", + "version": "3.8.5", "type": "module", "description": "This plugin adds `TypeScript` support to `eslint-plugin-import`", "repository": "git+https://github.com/import-js/eslint-import-resolver-typescript", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy