Skip to content

Commit fca6308

Browse files
Fix #1259 for no-unresolved, add caseSensitiveStrict option
1 parent 767f01a commit fca6308

File tree

5 files changed

+53
-11
lines changed

5 files changed

+53
-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

+6-4
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@ module.exports = {
1717

1818
schema: [ makeOptionsSchema({
1919
caseSensitive: { type: 'boolean', default: true },
20+
caseSensitiveStrict: { type: 'boolean', default: false },
2021
})],
2122
},
2223

2324
create: function (context) {
25+
const options = context.options[0] || {}
2426

2527
function checkSourceValue(source) {
26-
const shouldCheckCase = !CASE_SENSITIVE_FS &&
27-
(!context.options[0] || context.options[0].caseSensitive !== false)
28+
const shouldCheckCase = !CASE_SENSITIVE_FS && options.caseSensitive !== false
29+
const caseSensitiveStrict = !CASE_SENSITIVE_FS && options.caseSensitiveStrict
2830

2931
const resolvedPath = resolve(source.value, context)
3032

@@ -35,15 +37,15 @@ module.exports = {
3537

3638
else if (shouldCheckCase) {
3739
const cacheSettings = ModuleCache.getSettings(context.settings)
38-
if (!fileExistsWithCaseSync(resolvedPath, cacheSettings)) {
40+
if (!fileExistsWithCaseSync(resolvedPath, cacheSettings, caseSensitiveStrict)) {
3941
context.report(source,
4042
`Casing of ${source.value} does not match the underlying filesystem.`)
4143
}
4244

4345
}
4446
}
4547

46-
return moduleVisitor(checkSourceValue, context.options[0])
48+
return moduleVisitor(checkSourceValue, options)
4749

4850
},
4951
}

tests/src/core/resolve.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ describe('resolve', function () {
152152
const caseDescribe = (!CASE_SENSITIVE_FS ? describe : describe.skip)
153153
caseDescribe('case sensitivity', function () {
154154
let file
155-
const testContext = utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] }})
155+
const testContext = utils.testContext({
156+
'import/resolve': { 'extensions': ['.jsx'] },
157+
'import/cache': { lifetime: 0 },
158+
})
159+
const testSettings = testContext.settings
156160
before('resolve', function () {
157161
file = resolve(
158162
// Note the case difference 'MyUncoolComponent' vs 'MyUnCoolComponent'
@@ -162,14 +166,19 @@ describe('resolve', function () {
162166
expect(file, 'path to ./jsx/MyUncoolComponent').to.exist
163167
})
164168
it('detects case does not match FS', function () {
165-
expect(fileExistsWithCaseSync(file, ModuleCache.getSettings(testContext)))
169+
expect(fileExistsWithCaseSync(file, testSettings))
166170
.to.be.false
167171
})
168172
it('detecting case does not include parent folder path (issue #720)', function () {
169173
const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx')
170-
expect(fileExistsWithCaseSync(f, ModuleCache.getSettings(testContext), true))
174+
expect(fileExistsWithCaseSync(f, testSettings))
171175
.to.be.true
172176
})
177+
it('detecting case should include parent folder path', function () {
178+
const f = path.join(process.cwd().toUpperCase(), './tests/files/jsx/MyUnCoolComponent.jsx')
179+
expect(fileExistsWithCaseSync(f, testSettings, true))
180+
.to.be.false
181+
})
173182
})
174183

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

tests/src/rules/no-unresolved.js

+16-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)
@@ -203,12 +203,21 @@ function runResolverTests(resolver) {
203203
})
204204

205205
if (!CASE_SENSITIVE_FS) {
206+
const relativePath = './tests/files/jsx/MyUnCoolComponent.jsx'
207+
const cwd = process.cwd()
208+
const mismatchedPath = path.join(cwd.toUpperCase(), relativePath).replace(/\\/g, '/')
209+
206210
ruleTester.run('case sensitivity', rule, {
207211
valid: [
208212
rest({ // test with explicit flag
209213
code: 'import foo from "./jsx/MyUncoolComponent.jsx"',
210214
options: [{ caseSensitive: false }],
211215
}),
216+
// #1259 issue
217+
rest({ // test with explicit flag
218+
code: `import foo from "${mismatchedPath}"`,
219+
options: [{ caseSensitive: true }],
220+
}),
212221
],
213222

214223
invalid: [
@@ -221,6 +230,12 @@ function runResolverTests(resolver) {
221230
options: [{ caseSensitive: true }],
222231
errors: [`Casing of ./jsx/MyUncoolComponent.jsx does not match the underlying filesystem.`],
223232
}),
233+
// #1259 issue
234+
rest({ // test with explicit flag
235+
code: `import foo from "${mismatchedPath}"`,
236+
options: [{ caseSensitiveStrict: true }],
237+
errors: [`Casing of ${mismatchedPath} does not match the underlying filesystem.`],
238+
}),
224239
],
225240
})
226241
}

utils/resolve.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ function tryRequire(target) {
2929
}
3030

3131
// http://stackoverflow.com/a/27382838
32-
exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings) {
32+
exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings, strict) {
3333
// don't care if the FS is case-sensitive
3434
if (CASE_SENSITIVE_FS) return true
3535

3636
// null means it resolved to a builtin
3737
if (filepath === null) return true
38-
if (filepath.toLowerCase() === process.cwd().toLowerCase()) return true
38+
if (filepath.toLowerCase() === process.cwd().toLowerCase() && !strict) return true
3939
const parsedPath = path.parse(filepath)
4040
, dir = parsedPath.dir
4141

@@ -50,7 +50,7 @@ exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cache
5050
if (filenames.indexOf(parsedPath.base) === -1) {
5151
result = false
5252
} else {
53-
result = fileExistsWithCaseSync(dir, cacheSettings)
53+
result = fileExistsWithCaseSync(dir, cacheSettings, strict)
5454
}
5555
}
5656
fileExistsCache.set(filepath, result)

0 commit comments

Comments
 (0)