Skip to content

Commit 92c1943

Browse files
authored
fix: correctly iterate files matched by glob patterns (#16831)
* fix: correctly iterate files matched by glob patterns * test: add a test case for #14742 * test: improve test case * chore: remove .only * chore: revert unwanted changes * test: fix root path * chore: fix lint * fix: correctly iterate files matched by glob patterns for new config system * test: add case for flat config * chore: remove .only
1 parent 89d9844 commit 92c1943

8 files changed

Lines changed: 97 additions & 6 deletions

File tree

lib/cli-engine/file-enumerator.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ class FileEnumerator {
349349
return this._iterateFilesWithFile(absolutePath);
350350
}
351351
if (globInputPaths && isGlobPattern(pattern)) {
352-
return this._iterateFilesWithGlob(absolutePath, isDot);
352+
return this._iterateFilesWithGlob(pattern, isDot);
353353
}
354354

355355
return [];
@@ -398,15 +398,17 @@ class FileEnumerator {
398398
_iterateFilesWithGlob(pattern, dotfiles) {
399399
debug(`Glob: ${pattern}`);
400400

401-
const directoryPath = path.resolve(getGlobParent(pattern));
402-
const globPart = pattern.slice(directoryPath.length + 1);
401+
const { cwd } = internalSlotsMap.get(this);
402+
const directoryPath = path.resolve(cwd, getGlobParent(pattern));
403+
const absolutePath = path.resolve(cwd, pattern);
404+
const globPart = absolutePath.slice(directoryPath.length + 1);
403405

404406
/*
405407
* recursive if there are `**` or path separators in the glob part.
406408
* Otherwise, patterns such as `src/*.js`, it doesn't need recursive.
407409
*/
408410
const recursive = /\*\*|\/|\\/u.test(globPart);
409-
const selector = new Minimatch(pattern, minimatchOpts);
411+
const selector = new Minimatch(absolutePath, minimatchOpts);
410412

411413
debug(`recursive? ${recursive}`);
412414

lib/eslint/eslint-helpers.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,9 +526,9 @@ async function findFiles({
526526
}
527527

528528
// save patterns for later use based on whether globs are enabled
529-
if (globInputPaths && isGlobPattern(filePath)) {
529+
if (globInputPaths && isGlobPattern(pattern)) {
530530

531-
const basePath = globParent(filePath);
531+
const basePath = path.resolve(cwd, globParent(pattern));
532532

533533
// group in cwd if possible and split out others
534534
if (isPathInside(basePath, cwd)) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = { rules: { "no-console": "off" } };
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log("one");
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = { rules: { "no-console": "warn" } };
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log("two");

tests/lib/cli-engine/file-enumerator.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const path = require("path");
1313
const os = require("os");
1414
const { assert } = require("chai");
1515
const sh = require("shelljs");
16+
const sinon = require("sinon");
1617
const {
1718
Legacy: {
1819
CascadingConfigArrayFactory
@@ -182,6 +183,73 @@ describe("FileEnumerator", () => {
182183
});
183184
});
184185

186+
// https://github.com/eslint/eslint/issues/14742
187+
describe("with 5 directories ('{lib}', '{lib}/client', '{lib}/client/src', '{lib}/server', '{lib}/server/src') that contains two files '{lib}/client/src/one.js' and '{lib}/server/src/two.js'", () => {
188+
const root = path.join(os.tmpdir(), "eslint/file-enumerator");
189+
const files = {
190+
"{lib}/client/src/one.js": "console.log('one.js');",
191+
"{lib}/server/src/two.js": "console.log('two.js');",
192+
"{lib}/client/.eslintrc.json": JSON.stringify({
193+
rules: {
194+
"no-console": "error"
195+
},
196+
env: {
197+
mocha: true
198+
}
199+
}),
200+
"{lib}/server/.eslintrc.json": JSON.stringify({
201+
rules: {
202+
"no-console": "off"
203+
},
204+
env: {
205+
mocha: true
206+
}
207+
})
208+
};
209+
const { prepare, cleanup, getPath } = createCustomTeardown({
210+
cwd: root,
211+
files
212+
});
213+
214+
/** @type {FileEnumerator} */
215+
let enumerator;
216+
217+
beforeEach(async () => {
218+
await prepare();
219+
enumerator = new FileEnumerator({
220+
cwd: path.resolve(getPath("{lib}/server"))
221+
});
222+
});
223+
224+
afterEach(cleanup);
225+
226+
describe("when running eslint in the server directory", () => {
227+
it("should use the config '{lib}/server/.eslintrc.json' for '{lib}/server/src/two.js'.", () => {
228+
const spy = sinon.spy(fs, "readdirSync");
229+
230+
const list = [
231+
...enumerator.iterateFiles(["src/**/*.{js,json}"])
232+
];
233+
234+
// should enter the directory '{lib}/server/src' directly
235+
assert.strictEqual(spy.getCall(0).firstArg, path.join(root, "{lib}/server/src"));
236+
assert.strictEqual(list.length, 1);
237+
assert.strictEqual(list[0].config.length, 2);
238+
assert.strictEqual(list[0].config[0].name, "DefaultIgnorePattern");
239+
assert.strictEqual(list[0].config[1].filePath, getPath("{lib}/server/.eslintrc.json"));
240+
assert.deepStrictEqual(
241+
list.map(entry => entry.filePath),
242+
[
243+
path.join(root, "{lib}/server/src/two.js")
244+
]
245+
);
246+
247+
// destroy the spy
248+
sinon.restore();
249+
});
250+
});
251+
});
252+
185253
// This group moved from 'tests/lib/util/glob-utils.js' when refactoring to keep the cumulated test cases.
186254
describe("with 'tests/fixtures/glob-utils' files", () => {
187255
let fixtureDir;

tests/lib/eslint/flat-eslint.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,23 @@ describe("FlatESLint", () => {
850850
assert.strictEqual(results[0].suppressedMessages.length, 0);
851851
});
852852

853+
// https://github.com/eslint/eslint/issues/14742
854+
it("should run", async () => {
855+
eslint = new FlatESLint({
856+
cwd: getFixturePath("{curly-path}", "server")
857+
});
858+
const results = await eslint.lintFiles(["src/**/*.{js,json}"]);
859+
860+
assert.strictEqual(results.length, 1);
861+
assert.strictEqual(results[0].messages.length, 1);
862+
assert.strictEqual(results[0].messages[0].ruleId, "no-console");
863+
assert.strictEqual(
864+
results[0].filePath,
865+
getFixturePath("{curly-path}/server/src/two.js")
866+
);
867+
assert.strictEqual(results[0].suppressedMessages.length, 0);
868+
});
869+
853870
// https://github.com/eslint/eslint/issues/16265
854871
describe("Dot files in searches", () => {
855872

0 commit comments

Comments
 (0)