diff --git a/CHANGELOG.md b/CHANGELOG.md index 59bcfb4be3..ddba3b5fcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel ## [Unreleased] +### Added +- [`no-unresolved`]: add `caseSensitiveStrict` option ([#1262], thanks [@sergei-startsev]) + ## [2.24.1] - 2021-08-19 ### Fixed @@ -1042,6 +1045,7 @@ for info on changes for earlier releases. [#1294]: https://github.com/import-js/eslint-plugin-import/pull/1294 [#1290]: https://github.com/import-js/eslint-plugin-import/pull/1290 [#1277]: https://github.com/import-js/eslint-plugin-import/pull/1277 +[#1262]: https://github.com/import-js/eslint-plugin-import/pull/1262 [#1257]: https://github.com/import-js/eslint-plugin-import/pull/1257 [#1253]: https://github.com/import-js/eslint-plugin-import/pull/1253 [#1248]: https://github.com/import-js/eslint-plugin-import/pull/1248 diff --git a/docs/rules/no-unresolved.md b/docs/rules/no-unresolved.md index ae6177dfd9..89d00b9301 100644 --- a/docs/rules/no-unresolved.md +++ b/docs/rules/no-unresolved.md @@ -76,10 +76,25 @@ By default, this rule will report paths whose case do not match the underlying f const { default: x } = require('./foo') // reported if './foo' is actually './Foo' and caseSensitive: true ``` +#### `caseSensitiveStrict` + +The `caseSensitive` option does not detect case for the current working directory. The `caseSensitiveStrict` option allows checking `cwd` in resolved path. By default, the option is disabled. + + +```js +/*eslint import/no-unresolved: [2, { caseSensitiveStrict: true }]*/ + +// Absolute paths +import Foo from `/Users/fOo/bar/file.js` // reported, /Users/foo/bar/file.js +import Foo from `d:/fOo/bar/file.js` // reported, d:/foo/bar/file.js + +// Relative paths, cwd is Users/foo/ +import Foo from `./../fOo/bar/file.js` // reported +``` + ## When Not To Use It -If you're using a module bundler other than Node or Webpack, you may end up with -a lot of false positive reports of missing dependencies. +If you're using a module bundler other than Node or Webpack, you may end up with a lot of false positive reports of missing dependencies. ## Further Reading diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js index 719bbded9d..6ed009b1cf 100644 --- a/src/rules/no-unresolved.js +++ b/src/rules/no-unresolved.js @@ -18,14 +18,17 @@ module.exports = { schema: [ makeOptionsSchema({ caseSensitive: { type: 'boolean', default: true }, + caseSensitiveStrict: { type: 'boolean', default: false }, }), ], }, create: function (context) { + const options = context.options[0] || {}; + function checkSourceValue(source) { - const shouldCheckCase = !CASE_SENSITIVE_FS - && (!context.options[0] || context.options[0].caseSensitive !== false); + const caseSensitive = !CASE_SENSITIVE_FS && options.caseSensitive !== false; + const caseSensitiveStrict = !CASE_SENSITIVE_FS && options.caseSensitiveStrict; const resolvedPath = resolve(source.value, context); @@ -34,9 +37,9 @@ module.exports = { source, `Unable to resolve path to module '${source.value}'.` ); - } else if (shouldCheckCase) { + } else if (caseSensitive || caseSensitiveStrict) { const cacheSettings = ModuleCache.getSettings(context.settings); - if (!fileExistsWithCaseSync(resolvedPath, cacheSettings)) { + if (!fileExistsWithCaseSync(resolvedPath, cacheSettings, caseSensitiveStrict)) { context.report( source, `Casing of ${source.value} does not match the underlying filesystem.` @@ -45,6 +48,6 @@ module.exports = { } } - return moduleVisitor(checkSourceValue, context.options[0]); + return moduleVisitor(checkSourceValue, options); }, }; diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js index d21ee2fd8c..19203074e1 100644 --- a/tests/src/rules/no-unresolved.js +++ b/tests/src/rules/no-unresolved.js @@ -15,7 +15,7 @@ function runResolverTests(resolver) { function rest(specs) { specs.settings = Object.assign({}, specs.settings, - { 'import/resolver': resolver }, + { 'import/resolver': resolver, 'import/cache': { lifetime: 0 } }, ); return test(specs); @@ -227,6 +227,10 @@ function runResolverTests(resolver) { }); if (!CASE_SENSITIVE_FS) { + const relativePath = './tests/files/jsx/MyUnCoolComponent.jsx'; + const cwd = process.cwd(); + const mismatchedPath = path.join(cwd.toUpperCase(), relativePath).replace(/\\/g, '/'); + ruleTester.run('case sensitivity', rule, { valid: [ rest({ // test with explicit flag @@ -247,6 +251,29 @@ function runResolverTests(resolver) { }), ], }); + + ruleTester.run('case sensitivity strict', rule, { + valid: [ + // #1259 issue + rest({ // caseSensitiveStrict is disabled by default + code: `import foo from "${mismatchedPath}"`, + }), + ], + + invalid: [ + // #1259 issue + rest({ // test with enabled caseSensitiveStrict option + code: `import foo from "${mismatchedPath}"`, + options: [{ caseSensitiveStrict: true }], + errors: [`Casing of ${mismatchedPath} does not match the underlying filesystem.`], + }), + rest({ // test with enabled caseSensitiveStrict option and disabled caseSensitive + code: `import foo from "${mismatchedPath}"`, + options: [{ caseSensitiveStrict: true, caseSensitive: false }], + errors: [`Casing of ${mismatchedPath} does not match the underlying filesystem.`], + }), + ], + }); } }