Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Ensure flat config unignores work consistently like eslintrc #16579

Merged
merged 2 commits into from Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/config/default-config.js
Expand Up @@ -51,7 +51,7 @@ exports.defaultConfig = [
// default ignores are listed here
{
ignores: [
"**/node_modules/**",
"**/node_modules/*",
".git/"
]
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -56,7 +56,7 @@
"bugs": "https://github.com/eslint/eslint/issues/",
"dependencies": {
"@eslint/eslintrc": "^1.3.3",
"@humanwhocodes/config-array": "0.11.7",
"@humanwhocodes/config-array": "^0.11.8",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
"ajv": "^6.10.0",
Expand Down
99 changes: 74 additions & 25 deletions tests/lib/eslint/flat-eslint.js
Expand Up @@ -4502,19 +4502,13 @@ describe("FlatESLint", () => {
});


/*
* These tests fail due to a bug in fast-glob that doesn't allow
* negated patterns inside of ignores. These tests won't work until
* this bug is fixed:
* https://github.com/mrmlnc/fast-glob/issues/356
*/
xdescribe("ignorePatterns can unignore '/node_modules/foo'.", () => {
describe("ignores can unignore '/node_modules/foo'.", () => {

const { prepare, cleanup, getPath } = createCustomTeardown({
cwd: root,
cwd: `${root}-unignores`,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like there was some timing issues where just root was colliding due to Mocha running some tests in parallel, so I made them unique.

files: {
"eslint.config.js": `module.exports = {
ignores: ["!**/node_modules/foo/**"]
ignores: ["!**/node_modules/foo"]
};`,
"node_modules/foo/index.js": "",
"node_modules/foo/.dot.js": "",
Expand Down Expand Up @@ -4551,16 +4545,70 @@ describe("FlatESLint", () => {
.sort();

assert.deepStrictEqual(filePaths, [
path.join(root, "eslint.config.js"),
path.join(root, "foo.js"),
path.join(root, "node_modules/foo/index.js")
path.join(getPath(), "eslint.config.js"),
path.join(getPath(), "foo.js"),
path.join(getPath(), "node_modules/foo/.dot.js"),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now include dot files by default, so had to update tests accordingly.

path.join(getPath(), "node_modules/foo/index.js")
]);
});
});

xdescribe("ignore pattern can re-ignore files that are unignored by a previous pattern.", () => {
describe("ignores can unignore '/node_modules/foo/**'.", () => {

const { prepare, cleanup, getPath } = createCustomTeardown({
cwd: root,
cwd: `${root}-unignores`,
files: {
"eslint.config.js": `module.exports = {
ignores: ["!**/node_modules/foo/**"]
};`,
"node_modules/foo/index.js": "",
"node_modules/foo/.dot.js": "",
"node_modules/bar/index.js": "",
"foo.js": ""
}
});

beforeEach(prepare);
afterEach(cleanup);

it("'isPathIgnored()' should return 'true' for 'node_modules/foo/index.js'.", async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it("'isPathIgnored()' should return 'true' for 'node_modules/foo/index.js'.", async () => {
it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", async () => {

Test title doesn't match the assertion in the test.

The assertion is correct. node_modules/foo/ is ignored by default, but since **/node_modules/foo/** now matches node_modules/foo/, !**/node_modules/foo/** will unignore it, so the files inside are not ignored.

const engine = new FlatESLint({ cwd: getPath() });

assert.strictEqual(await engine.isPathIgnored("node_modules/foo/index.js"), false);
});

it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", async () => {
it("'isPathIgnored()' should return 'false' for 'node_modules/foo/.dot.js'.", async () => {

Same as the previous, the test is correct just the title should be updated.

const engine = new FlatESLint({ cwd: getPath() });

assert.strictEqual(await engine.isPathIgnored("node_modules/foo/.dot.js"), false);
});

it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", async () => {
const engine = new FlatESLint({ cwd: getPath() });

assert.strictEqual(await engine.isPathIgnored("node_modules/bar/index.js"), true);
});

it("'lintFiles()' should verify 'node_modules/foo/index.js'.", async () => {
const engine = new FlatESLint({ cwd: getPath() });
const result = (await engine.lintFiles("**/*.js"));

const filePaths = result
.map(r => r.filePath)
.sort();

assert.deepStrictEqual(filePaths, [
path.join(getPath(), "eslint.config.js"),
path.join(getPath(), "foo.js"),
path.join(getPath(), "node_modules/foo/.dot.js"),
path.join(getPath(), "node_modules/foo/index.js")
]);
});
});

describe("ignore pattern can re-ignore files that are unignored by a previous pattern.", () => {
const { prepare, cleanup, getPath } = createCustomTeardown({
cwd: `${root}-reignore`,
files: {
"eslint.config.js": `module.exports = ${JSON.stringify({
ignores: ["!.*", ".foo*"]
Expand Down Expand Up @@ -4592,15 +4640,15 @@ describe("FlatESLint", () => {
.sort();

assert.deepStrictEqual(filePaths, [
path.join(root, ".bar.js"),
path.join(root, "eslint.config.js")
path.join(getPath(), ".bar.js"),
path.join(getPath(), "eslint.config.js")
]);
});
});

xdescribe("ignore pattern can unignore files that are ignored by a previous pattern.", () => {
describe("ignore pattern can unignore files that are ignored by a previous pattern.", () => {
const { prepare, cleanup, getPath } = createCustomTeardown({
cwd: root,
cwd: `${root}-dignore`,
files: {
"eslint.config.js": `module.exports = ${JSON.stringify({
ignores: ["**/*.js", "!foo.js"]
Expand Down Expand Up @@ -4632,7 +4680,7 @@ describe("FlatESLint", () => {
.sort();

assert.deepStrictEqual(filePaths, [
path.join(root, "foo.js")
path.join(getPath(), "foo.js")
]);
});
});
Expand Down Expand Up @@ -5033,17 +5081,17 @@ describe("FlatESLint", () => {
});
});

// dependent on https://github.com/mrmlnc/fast-glob/issues/86
xdescribe("if { ignores: 'foo/*.js', ... } is present by '--config node_modules/myconf/eslint.config.js',", () => {
describe("if { ignores: 'foo/*.js', ... } is present by '--config node_modules/myconf/eslint.config.js',", () => {
const { prepare, cleanup, getPath } = createCustomTeardown({
cwd: `${root}a3`,
files: {
"node_modules/myconf/eslint.config.js": `module.exports = {
ignores: ["**/eslint.config.js", "!node_modules/myconf", "foo/*.js"],
"node_modules/myconf/eslint.config.js": `module.exports = [{
ignores: ["!node_modules/myconf", "foo/*.js"],
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove "**/eslint.config.js" from this array. With ignorePatterns, that file would be ignored; with ignores, the file isn't ignored due to "!node_module/myconf unignoring the whole directory, which overrides "**/eslint.config.js".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!node_modules/myconf also shouldn't have any effects after **/node_modules/**. because it unignores the directory but everything under it is still ignored by **/node_modules/**.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also seems counter to what existing tests are indicating. 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the original test:
https://github.com/eslint/eslint/blob/main/tests/lib/eslint/eslint.js#L6426-L6459

It seems to behave in the same way as I have currently.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the original test: https://github.com/eslint/eslint/blob/main/tests/lib/eslint/eslint.js#L6426-L6459

This is a bit different because in eslintrc the default pattern is /**/node_modules/* (* instead of ** at the end is the difference; leading slash doesn't matter), so in the original test the list of patterns is:

/**/node_modules/*
!/node_modules/myconf

node_modules/ doesn't match any patterns; node_modules/myconf/ matches /**/node_modules/* but also matches a subsequent negative pattern !/node_modules/myconf so it's not ignored; node_modules/myconf/foo/ doesn't match any patterns; node_modules/myconf/foo/test.js doesn't match any patterns.

In the flat eslint test, the list of patterns is:

**/node_modules/**
!node_modules/myconf

node_modules/ doesn't match any patterns; node_modules/myconf/ matches **/node_modules/* but also matches a subsequent negative pattern !node_modules/myconf so it's not ignored; node_modules/myconf/foo/ matches **/node_modules/** and doesn't match any negative patterns so that should be the end - directory node_modules/myconf/foo/ is ignored and thus everything under it is ignored as well, including node_modules/myconf/foo/test.js.

}, {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to separate into a different config object so ignores is treated as global ignores.

rules: {
eqeqeq: "error"
}
}`,
}]`,
"node_modules/myconf/foo/test.js": "a == b",
"foo/test.js": "a == b"
}
Expand All @@ -5052,7 +5100,7 @@ describe("FlatESLint", () => {
beforeEach(prepare);
afterEach(cleanup);

it("'lintFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", async () => {
it("'lintFiles()' with '**/*.js' should lint 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", async () => {
const engine = new FlatESLint({
overrideConfigFile: "node_modules/myconf/eslint.config.js",
cwd: getPath()
Expand All @@ -5062,6 +5110,7 @@ describe("FlatESLint", () => {
.sort();

assert.deepStrictEqual(files, [
path.join(getPath(), "node_modules/myconf/eslint.config.js"),
path.join(getPath(), "node_modules/myconf/foo/test.js")
]);
});
Expand Down