diff --git a/lib/cli-engine/file-enumerator.js b/lib/cli-engine/file-enumerator.js index c2961d71ac0..bd89ec7334c 100644 --- a/lib/cli-engine/file-enumerator.js +++ b/lib/cli-engine/file-enumerator.js @@ -433,9 +433,14 @@ class FileEnumerator { // Enumerate the files of this directory. for (const entry of readdirSafeSync(directoryPath)) { const filePath = path.join(directoryPath, entry.name); + const fileInfo = entry.isSymbolicLink() ? statSafeSync(filePath) : entry; + + if (!fileInfo) { + continue; + } // Check if the file is matched. - if (entry.isFile()) { + if (fileInfo.isFile()) { if (!config) { config = configArrayFactory.getConfigArrayForFile( filePath, @@ -471,7 +476,7 @@ class FileEnumerator { } // Dive into the sub directory. - } else if (options.recursive && entry.isDirectory()) { + } else if (options.recursive && fileInfo.isDirectory()) { if (!config) { config = configArrayFactory.getConfigArrayForFile( filePath, diff --git a/tests/lib/cli-engine/file-enumerator.js b/tests/lib/cli-engine/file-enumerator.js index 3ea51a408c8..1ea7a3bd2c4 100644 --- a/tests/lib/cli-engine/file-enumerator.js +++ b/tests/lib/cli-engine/file-enumerator.js @@ -487,6 +487,50 @@ describe("FileEnumerator", () => { }); }); }); + + describe("if contains symbolic links", async () => { + const root = path.join(os.tmpdir(), "eslint/file-enumerator"); + const files = { + "dir1/1.js": "", + "dir1/2.js": "", + "top-level.js": "", + ".eslintrc.json": JSON.stringify({ rules: {} }) + }; + const dir2 = path.join(root, "dir2"); + const { prepare, cleanup } = createCustomTeardown({ cwd: root, files }); + + beforeEach(async () => { + await prepare(); + fs.mkdirSync(dir2); + fs.symlinkSync(path.join(root, "top-level.js"), path.join(dir2, "top.js"), "file"); + fs.symlinkSync(path.join(root, "dir1"), path.join(dir2, "nested"), "dir"); + }); + + afterEach(cleanup); + + it("should resolve", () => { + const enumerator = new FileEnumerator({ cwd: root }); + const list = Array.from(enumerator.iterateFiles(["dir2/**/*.js"])).map(({ filePath }) => filePath); + + assert.deepStrictEqual(list, [ + path.join(dir2, "nested", "1.js"), + path.join(dir2, "nested", "2.js"), + path.join(dir2, "top.js") + ]); + }); + + it("should ignore broken links", () => { + fs.unlinkSync(path.join(root, "top-level.js")); + + const enumerator = new FileEnumerator({ cwd: root }); + const list = Array.from(enumerator.iterateFiles(["dir2/**/*.js"])).map(({ filePath }) => filePath); + + assert.deepStrictEqual(list, [ + path.join(dir2, "nested", "1.js"), + path.join(dir2, "nested", "2.js") + ]); + }); + }); }); // https://github.com/eslint/eslint/issues/13789