diff --git a/tests/files/load-error-resolver.js b/tests/files/load-error-resolver.js new file mode 100644 index 000000000..aa9d33010 --- /dev/null +++ b/tests/files/load-error-resolver.js @@ -0,0 +1 @@ +throw new Error('TEST ERROR') diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js index 307befcde..3c15303ed 100644 --- a/tests/src/core/resolve.js +++ b/tests/src/core/resolve.js @@ -118,6 +118,22 @@ describe('resolve', function () { )).to.equal(utils.testFilePath('./jsx/MyCoolComponent.jsx')) }) + it('reports load exception in a user resolver', function () { + + const testContext = utils.testContext({ 'import/resolver': './load-error-resolver' }) + const testContextReports = [] + testContext.report = function (reportInfo) { + testContextReports.push(reportInfo) + } + + expect(resolve( '../files/exception' + , Object.assign({}, testContext, { getFilename: function () { return utils.getFilename('exception.js') } }) + )).to.equal(undefined) + expect(testContextReports[0]).to.be.an('object') + expect(testContextReports[0].message).to.equal('Resolve error: TEST ERROR') + expect(testContextReports[0].loc).to.eql({ line: 1, column: 0 }) + }) + const caseDescribe = (!CASE_SENSITIVE_FS ? describe : describe.skip) caseDescribe('case sensitivity', function () { let file diff --git a/utils/resolve.js b/utils/resolve.js index 8193e7731..b280ca2cf 100644 --- a/utils/resolve.js +++ b/utils/resolve.js @@ -14,6 +14,20 @@ exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS const fileExistsCache = new ModuleCache() +function tryRequire(target) { + let resolved; + try { + // Check if the target exists + resolved = require.resolve(target); + } catch(e) { + // If the target does not exist then just return undefined + return undefined; + } + + // If the target exists then return the loaded module + return require(resolved); +} + // http://stackoverflow.com/a/27382838 exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings) { // don't care if the FS is case-sensitive @@ -135,27 +149,20 @@ function resolverReducer(resolvers, map) { throw new Error('invalid resolver config') } +function getBaseDir(sourceFile) { + return pkgDir.sync(sourceFile) || process.cwd() +} function requireResolver(name, sourceFile) { // Try to resolve package with conventional name - try { - return require(`eslint-import-resolver-${name}`) - } catch (err) { /* continue */ } + let resolver = tryRequire(`eslint-import-resolver-${name}`) || + tryRequire(name) || + tryRequire(path.resolve(getBaseDir(sourceFile), name)) - // Try to resolve package with custom name (@myorg/resolver-name) - try { - return require(name) - } catch (err) { /* continue */ } - - // Try to resolve package with path, relative to closest package.json - // or current working directory - try { - const baseDir = pkgDir.sync(sourceFile) || process.cwd() - // absolute paths ignore base, so this covers both - return require(path.resolve(baseDir, name)) - } catch (err) { /* continue */ } - - // all else failed - throw new Error(`unable to load resolver "${name}".`) + if (!resolver) { + throw new Error(`unable to load resolver "${name}".`) + } else { + return resolver; + } } const erroredContexts = new Set()