From 5d771a330f91140a9157e74cbdb648a3ddbd0eea Mon Sep 17 00:00:00 2001 From: SimeonC <1085899+SimeonC@users.noreply.github.com> Date: Wed, 1 Nov 2023 18:02:15 +0900 Subject: [PATCH] fix: shortest import should prefer alias with `~` at the start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves the following scenario; * `../Common/ShopSelect` * `~/Common/ShopSelect` These are considered “same length” but we want to prefer the `~` alias path as it’s easier to read than the relative path. Found and fixed another preferred alias’ bug. --- .../__tests__/shortestImport.test.ts | 9 +++++ packages/eslint-plugin/src/shortestImport.ts | 33 ++++++++++--------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/packages/eslint-plugin/__tests__/shortestImport.test.ts b/packages/eslint-plugin/__tests__/shortestImport.test.ts index 96335c52..99e58d7d 100644 --- a/packages/eslint-plugin/__tests__/shortestImport.test.ts +++ b/packages/eslint-plugin/__tests__/shortestImport.test.ts @@ -172,11 +172,20 @@ typescriptSetups.forEach((config) => { path: '~/feature2/index', filename: './test_src/feature1/slice1/index.ts', }, + { + path: '~/feature2/index', + filename: './test_src/feature1/index.ts', + }, { path: '~/feature1/index', filename: './test_src/feature1/slice1/index.ts', options: [['~/feature1', 'feature1']], }, + { + path: '~/feature1/slice1', + filename: './test_src/feature1/index.ts', + options: [['~/feature1', 'feature1']], + }, { path: '@node/module', filename: './test_src/feature1/slice1/inner1/index.ts', diff --git a/packages/eslint-plugin/src/shortestImport.ts b/packages/eslint-plugin/src/shortestImport.ts index 73a87573..fa39d8aa 100644 --- a/packages/eslint-plugin/src/shortestImport.ts +++ b/packages/eslint-plugin/src/shortestImport.ts @@ -156,7 +156,7 @@ class RuleChecker { relativePath, aliasPaths, baseUrlPaths, - avoidRelativeParents: context.options[0] || [], + preferredAliasPaths: context.options[0] || [], }); if (preferredPath === importPath) return; @@ -270,31 +270,34 @@ class RuleChecker { relativePath, aliasPaths, baseUrlPaths, - avoidRelativeParents, + preferredAliasPaths, }: { resolvedFilePath: string; relativePath: string; aliasPaths: string[]; baseUrlPaths: string[]; - avoidRelativeParents: string[]; + preferredAliasPaths: string[]; }) { if (!aliasPaths.length && !baseUrlPaths.length) return relativePath; - const parentSlugs = relativePath.split('/').filter((s) => s === '..'); const shouldAvoidRelative = this.relativeGoesThroughBaseUrl(relativePath, resolvedFilePath) || [...aliasPaths, ...baseUrlPaths].some((aliasPath) => { - if (!avoidRelativeParents.length) return false; - const relativeRoot = aliasPath - .split('/') - .slice(0, -1 * parentSlugs.length) - .join('/'); - return avoidRelativeParents.includes(relativeRoot); + if (!preferredAliasPaths.length) return false; + return preferredAliasPaths.some((alias) => aliasPath.startsWith(alias)); }); const allPathsWithLength = (aliasPaths.length ? aliasPaths : baseUrlPaths) - .map((aliasPath) => ({ - aliasPath, - length: aliasPath.split('/').length, - })) + .map((aliasPath) => { + const parts = aliasPath.split('/'); + if (parts[0].match(/^[^a-z0-9]$/i)) + return { + aliasPath, + length: parts.length - 1, + }; + return { + aliasPath, + length: parts.length, + }; + }) .sort((a, b) => a.length - b.length); const shortestAliasPath = allPathsWithLength[0]; @@ -413,7 +416,7 @@ export const shortestImport: TSESLint.RuleModule< type: 'problem', docs: { description: - 'Enforce the consistent use of preferred import paths. A list of alias paths to prefer over relative `../` paths can also be provided', + 'Enforce the consistent use of preferred import paths. A list of alias paths to prefer over relative paths can also be provided', recommended: 'stylistic', }, fixable: 'code',