Skip to content

Commit aec4328

Browse files
Fix #1259 for no-unresolved, add caseSensitiveStrict option
1 parent aa8d566 commit aec4328

File tree

5 files changed

+61
-11
lines changed

5 files changed

+61
-11
lines changed

docs/rules/no-unresolved.md

+16
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,22 @@ By default, this rule will report paths whose case do not match the underlying f
7676
const { default: x } = require('./foo') // reported if './foo' is actually './Foo' and caseSensitive: true
7777
```
7878

79+
#### `caseSensitiveStrict`
80+
81+
`caseSensitive` option does not detect case for current working derectory, `caseSensitiveStrict` option allows to check `cwd` in resolved path. By default, the options is disabled.
82+
83+
84+
```js
85+
/*eslint import/no-unresolved: [2, { caseSensitiveStrict: true }]*/
86+
87+
// Absolute paths
88+
import Foo from `/Users/fOo/bar/file.js` // reported, /Users/foo/bar/file.js
89+
import Foo from `d:/fOo/bar/file.js` // reported, d:/foo/bar/file.js
90+
91+
// Relative paths, cwd is Users/foo/
92+
import Foo from `./../fOo/bar/file.js` // reported
93+
```
94+
7995
## When Not To Use It
8096

8197
If you're using a module bundler other than Node or Webpack, you may end up with

src/rules/no-unresolved.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@ module.exports = {
1818
schema: [
1919
makeOptionsSchema({
2020
caseSensitive: { type: 'boolean', default: true },
21+
caseSensitiveStrict: { type: 'boolean', default: false },
2122
}),
2223
],
2324
},
2425

2526
create: function (context) {
27+
const options = context.options[0] || {};
28+
2629
function checkSourceValue(source) {
27-
const shouldCheckCase = !CASE_SENSITIVE_FS
28-
&& (!context.options[0] || context.options[0].caseSensitive !== false);
30+
const shouldCheckCase = !CASE_SENSITIVE_FS && options.caseSensitive !== false;
31+
const caseSensitiveStrict = !CASE_SENSITIVE_FS && options.caseSensitiveStrict;
2932

3033
const resolvedPath = resolve(source.value, context);
3134

@@ -36,7 +39,7 @@ module.exports = {
3639
);
3740
} else if (shouldCheckCase) {
3841
const cacheSettings = ModuleCache.getSettings(context.settings);
39-
if (!fileExistsWithCaseSync(resolvedPath, cacheSettings)) {
42+
if (!fileExistsWithCaseSync(resolvedPath, cacheSettings, caseSensitiveStrict)) {
4043
context.report(
4144
source,
4245
`Casing of ${source.value} does not match the underlying filesystem.`
@@ -45,6 +48,6 @@ module.exports = {
4548
}
4649
}
4750

48-
return moduleVisitor(checkSourceValue, context.options[0]);
51+
return moduleVisitor(checkSourceValue, options);
4952
},
5053
};

tests/src/core/resolve.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,11 @@ describe('resolve', function () {
319319
const caseDescribe = (!CASE_SENSITIVE_FS ? describe : describe.skip);
320320
caseDescribe('case sensitivity', function () {
321321
let file;
322-
const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] } });
322+
const testContext = utils.testContext({
323+
'import/resolve': { 'extensions': ['.jsx'] },
324+
'import/cache': { lifetime: 0 },
325+
});
326+
const testSettings = testContext.settings;
323327
before('resolve', function () {
324328
file = resolve(
325329
// Note the case difference 'MyUncoolComponent' vs 'MyUnCoolComponent'
@@ -329,14 +333,19 @@ describe('resolve', function () {
329333
expect(file, 'path to ./jsx/MyUncoolComponent').to.exist;
330334
});
331335
it('detects case does not match FS', function () {
332-
expect(fileExistsWithCaseSync(file, ModuleCache.getSettings(testContext)))
336+
expect(fileExistsWithCaseSync(file, testSettings))
333337
.to.be.false;
334338
});
335339
it('detecting case does not include parent folder path (issue #720)', function () {
336340
const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx');
337-
expect(fileExistsWithCaseSync(f, ModuleCache.getSettings(testContext), true))
341+
expect(fileExistsWithCaseSync(f, testSettings))
338342
.to.be.true;
339343
});
344+
it('detecting case should include parent folder path', function () {
345+
const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx');
346+
expect(fileExistsWithCaseSync(f, testSettings, true))
347+
.to.be.false;
348+
});
340349
});
341350

342351
describe('rename cache correctness', function () {

tests/src/rules/no-unresolved.js

+23-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function runResolverTests(resolver) {
1515
function rest(specs) {
1616
specs.settings = Object.assign({},
1717
specs.settings,
18-
{ 'import/resolver': resolver },
18+
{ 'import/resolver': resolver, 'import/cache': { lifetime: 0 }, }
1919
);
2020

2121
return test(specs);
@@ -227,6 +227,10 @@ function runResolverTests(resolver) {
227227
});
228228

229229
if (!CASE_SENSITIVE_FS) {
230+
const relativePath = './tests/files/jsx/MyUnCoolComponent.jsx';
231+
const cwd = process.cwd();
232+
const mismatchedPath = path.join(cwd.toUpperCase(), relativePath).replace(/\\/g, '/');
233+
230234
ruleTester.run('case sensitivity', rule, {
231235
valid: [
232236
rest({ // test with explicit flag
@@ -247,6 +251,24 @@ function runResolverTests(resolver) {
247251
}),
248252
],
249253
});
254+
255+
ruleTester.run('case sensitivity strict', rule, {
256+
valid: [
257+
// #1259 issue
258+
rest({ // caseSensitiveStrict is disabled by default
259+
code: `import foo from "${mismatchedPath}"`,
260+
}),
261+
],
262+
263+
invalid: [
264+
// #1259 issue
265+
rest({ // test with enabled caseSensitiveStrict option
266+
code: `import foo from "${mismatchedPath}"`,
267+
options: [{ caseSensitiveStrict: true }],
268+
errors: [`Casing of ${mismatchedPath} does not match the underlying filesystem.`],
269+
}),
270+
],
271+
});
250272
}
251273

252274
}

utils/resolve.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ function tryRequire(target, sourceFile) {
5252
}
5353

5454
// http://stackoverflow.com/a/27382838
55-
exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings) {
55+
exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings, strict) {
5656
// don't care if the FS is case-sensitive
5757
if (CASE_SENSITIVE_FS) return true;
5858

5959
// null means it resolved to a builtin
6060
if (filepath === null) return true;
61-
if (filepath.toLowerCase() === process.cwd().toLowerCase()) return true;
61+
if (filepath.toLowerCase() === process.cwd().toLowerCase() && !strict) return true;
6262
const parsedPath = path.parse(filepath);
6363
const dir = parsedPath.dir;
6464

@@ -73,7 +73,7 @@ exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cache
7373
if (filenames.indexOf(parsedPath.base) === -1) {
7474
result = false;
7575
} else {
76-
result = fileExistsWithCaseSync(dir, cacheSettings);
76+
result = fileExistsWithCaseSync(dir, cacheSettings, strict);
7777
}
7878
}
7979
fileExistsCache.set(filepath, result);

0 commit comments

Comments
 (0)