Skip to content

Commit 366eeaf

Browse files
fix: if file has no corresponding mapper function, apply all of them… (#372)
1 parent b813788 commit 366eeaf

File tree

17 files changed

+128
-28
lines changed

17 files changed

+128
-28
lines changed

.changeset/long-insects-tan.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-import-resolver-typescript': patch
3+
---
4+
5+
fix: if file has no corresponding mapper function, apply all of them, starting with the nearest one.

.size-limit.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[
22
{
33
"path": "./lib/index.js",
4-
"limit": "3kB"
4+
"limit": "3.1kB"
55
}
66
]

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"test:importXResolverV3": "cross-env ESLINT_USE_FLAT_CONFIG=true eslint --config=tests/importXResolverV3/eslint.config.js tests/importXResolverV3",
5858
"test:multipleEslintrcs": "eslint --ext ts,tsx tests/multipleEslintrcs",
5959
"test:multipleTsconfigs": "eslint --ext ts,tsx tests/multipleTsconfigs",
60+
"test:nearestTsconfig": "eslint --ext ts,tsx tests/nearestTsconfig",
6061
"test:withJsExtension": "node tests/withJsExtension/test.js && eslint --ext ts,tsx tests/withJsExtension",
6162
"test:withJsconfig": "eslint --ext js tests/withJsconfig",
6263
"test:withPaths": "eslint --ext ts,tsx tests/withPaths",

src/index.ts

+64-27
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ let prevCwd: string
112112

113113
let mappersCachedOptions: InternalResolverOptions
114114
let mappers: Array<{
115+
path: string
115116
files: Set<string>
116117
mapperFn: NonNullable<ReturnType<typeof createPathsMatcher>>
117118
}> = []
@@ -311,35 +312,50 @@ function getMappedPaths(
311312
paths = [resolved]
312313
}
313314
} else {
314-
paths = [
315-
...new Set(
316-
mappers
317-
.filter(({ files }) => files.has(file))
318-
.map(({ mapperFn }) =>
319-
mapperFn(source).map(item => [
320-
...extensions.map(ext => `${item}${ext}`),
321-
...originalExtensions.map(ext => `${item}/index${ext}`),
322-
]),
323-
)
324-
.flat(2)
325-
.map(toNativePathSeparator),
326-
),
327-
].filter(mappedPath => {
328-
try {
329-
const stat = fs.statSync(mappedPath, { throwIfNoEntry: false })
330-
if (stat === undefined) return false
331-
if (stat.isFile()) return true
332-
333-
// Maybe this is a module dir?
334-
if (stat.isDirectory()) {
335-
return isModule(mappedPath)
315+
// Filter mapper functions associated with file
316+
let mapperFns: Array<NonNullable<ReturnType<typeof createPathsMatcher>>> =
317+
mappers
318+
.filter(({ files }) => files.has(file))
319+
.map(({ mapperFn }) => mapperFn)
320+
if (mapperFns.length === 0) {
321+
// If empty, try all mapper functions, starting with the nearest one
322+
mapperFns = mappers
323+
.map(mapper => ({
324+
mapperFn: mapper.mapperFn,
325+
counter: equalChars(path.dirname(file), path.dirname(mapper.path)),
326+
}))
327+
.sort(
328+
(a, b) =>
329+
// Sort in descending order where the nearest one has the longest counter
330+
b.counter - a.counter,
331+
)
332+
.map(({ mapperFn }) => mapperFn)
333+
}
334+
paths = mapperFns
335+
.map(mapperFn =>
336+
mapperFn(source).map(item => [
337+
...extensions.map(ext => `${item}${ext}`),
338+
...originalExtensions.map(ext => `${item}/index${ext}`),
339+
]),
340+
)
341+
.flat(2)
342+
.map(toNativePathSeparator)
343+
.filter(mappedPath => {
344+
try {
345+
const stat = fs.statSync(mappedPath, { throwIfNoEntry: false })
346+
if (stat === undefined) return false
347+
if (stat.isFile()) return true
348+
349+
// Maybe this is a module dir?
350+
if (stat.isDirectory()) {
351+
return isModule(mappedPath)
352+
}
353+
} catch {
354+
return false
336355
}
337-
} catch {
338-
return false
339-
}
340356

341-
return false
342-
})
357+
return false
358+
})
343359
}
344360

345361
if (retry && paths.length === 0) {
@@ -487,6 +503,7 @@ function initMappers(options: InternalResolverOptions) {
487503
}
488504

489505
return {
506+
path: toNativePathSeparator(tsconfigResult.path),
490507
files: new Set(files.map(toNativePathSeparator)),
491508
mapperFn,
492509
}
@@ -551,3 +568,23 @@ function toNativePathSeparator(p: string) {
551568
function isDefined<T>(value: T | null | undefined): value is T {
552569
return value !== null && value !== undefined
553570
}
571+
572+
/**
573+
* Counts how many characters in strings `a` and `b` are exactly the same and in the same position.
574+
*
575+
* @param {string} a First string
576+
* @param {string} b Second string
577+
* @returns Number of matching characters
578+
*/
579+
function equalChars(a: string, b: string): number {
580+
if (a.length === 0 || b.length === 0) {
581+
return 0
582+
}
583+
584+
let i = 0
585+
const length = Math.min(a.length, b.length)
586+
while (i < length && a.charAt(i) === b.charAt(i)) {
587+
i += 1
588+
}
589+
return i
590+
}

tests/nearestTsconfig/.eslintrc.cjs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const path = require('node:path')
2+
3+
const project = [
4+
'tsconfig.json',
5+
'a/tsconfig.json',
6+
'a/b/tsconfig.json',
7+
'a/b/c/tsconfig.json',
8+
].map(tsconfig => path.resolve(__dirname, tsconfig))
9+
10+
module.exports = require('../baseEslintConfig.cjs')(project)

tests/nearestTsconfig/a/app/app.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import 'components/a'
2+
import 'components/root'

tests/nearestTsconfig/a/b/app/app.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import 'components/b'
2+
import 'components/root'
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import 'components/c'
2+
import 'components/root'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default 'c'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"paths": {
5+
"components/*": ["../../../components/*", "./components/*"]
6+
}
7+
},
8+
"files": ["components/c.ts"]
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default 'b'
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"paths": {
5+
"components/*": ["../../components/*", "./components/*"]
6+
}
7+
},
8+
"files": ["components/b.ts"]
9+
}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default 'a'

tests/nearestTsconfig/a/tsconfig.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"paths": {
5+
"components/*": ["../components/*", "./components/*"]
6+
}
7+
},
8+
"files": ["components/a.ts"]
9+
}

tests/nearestTsconfig/app/app.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import 'components/root'
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default 'root'

tests/nearestTsconfig/tsconfig.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"paths": {
5+
"components/*": ["./components/*"]
6+
}
7+
},
8+
"files": ["components/root.ts"]
9+
}

0 commit comments

Comments
 (0)