Skip to content

Commit

Permalink
fix: validate ignorePatterns constructor option in FlatESLint cla…
Browse files Browse the repository at this point in the history
…ss (#17139)

* fix: validate `ignorePatterns` constructor option in `FlatESLint` class

* disallow string value
  • Loading branch information
mdjermanovic committed May 9, 2023
1 parent b1516db commit 0c415cd
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 33 deletions.
3 changes: 3 additions & 0 deletions lib/eslint/eslint-helpers.js
Expand Up @@ -758,6 +758,9 @@ function processOptions({
if (typeof ignore !== "boolean") {
errors.push("'ignore' must be a boolean.");
}
if (!isArrayOfNonEmptyString(ignorePatterns) && ignorePatterns !== null) {
errors.push("'ignorePatterns' must be an array of non-empty strings or null.");
}
if (typeof overrideConfig !== "object") {
errors.push("'overrideConfig' must be an object or null.");
}
Expand Down
50 changes: 22 additions & 28 deletions lib/eslint/flat-eslint.js
Expand Up @@ -76,7 +76,7 @@ const LintResultCache = require("../cli-engine/lint-result-cache");
* @property {string[]} [fixTypes] Array of rule types to apply fixes for.
* @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
* @property {boolean} [ignore] False disables all ignore patterns except for the default ones.
* @property {string[]} [ignorePatterns] Ignore file patterns to use in addition to config ignores.
* @property {string[]} [ignorePatterns] Ignore file patterns to use in addition to config ignores. These patterns are relative to `cwd`.
* @property {ConfigData} [overrideConfig] Override config object, overrides all configs used with this instance
* @property {boolean|string} [overrideConfigFile] Searches for default config file when falsy;
* doesn't do any config file lookup when `true`; considered to be a config filename
Expand Down Expand Up @@ -404,45 +404,39 @@ async function calculateConfigArray(eslint, {
// add in any configured defaults
configs.push(...slots.defaultConfigs);

let allIgnorePatterns = [];

// append command line ignore patterns
if (ignorePatterns) {
if (typeof ignorePatterns === "string") {
allIgnorePatterns.push(ignorePatterns);
} else {
allIgnorePatterns.push(...ignorePatterns);
}
}
if (ignorePatterns && ignorePatterns.length > 0) {

/*
* If the config file basePath is different than the cwd, then
* the ignore patterns won't work correctly. Here, we adjust the
* ignore pattern to include the correct relative path. Patterns
* loaded from ignore files are always relative to the cwd, whereas
* the config file basePath can be an ancestor of the cwd.
*/
if (basePath !== cwd && allIgnorePatterns.length) {
let relativeIgnorePatterns;

const relativeIgnorePath = path.relative(basePath, cwd);
/*
* If the config file basePath is different than the cwd, then
* the ignore patterns won't work correctly. Here, we adjust the
* ignore pattern to include the correct relative path. Patterns
* passed as `ignorePatterns` are relative to the cwd, whereas
* the config file basePath can be an ancestor of the cwd.
*/
if (basePath === cwd) {
relativeIgnorePatterns = ignorePatterns;
} else {

allIgnorePatterns = allIgnorePatterns.map(pattern => {
const negated = pattern.startsWith("!");
const basePattern = negated ? pattern.slice(1) : pattern;
const relativeIgnorePath = path.relative(basePath, cwd);

return (negated ? "!" : "") +
path.posix.join(relativeIgnorePath, basePattern);
});
}
relativeIgnorePatterns = ignorePatterns.map(pattern => {
const negated = pattern.startsWith("!");
const basePattern = negated ? pattern.slice(1) : pattern;

if (allIgnorePatterns.length) {
return (negated ? "!" : "") +
path.posix.join(relativeIgnorePath, basePattern);
});
}

/*
* Ignore patterns are added to the end of the config array
* so they can override default ignores.
*/
configs.push({
ignores: allIgnorePatterns
ignores: relativeIgnorePatterns
});
}

Expand Down
40 changes: 35 additions & 5 deletions tests/lib/eslint/flat-eslint.js
Expand Up @@ -182,6 +182,7 @@ describe("FlatESLint", () => {
fixTypes: ["xyz"],
globInputPaths: "",
ignore: "",
ignorePatterns: "",
overrideConfig: "",
overrideConfigFile: "",
plugins: "",
Expand All @@ -199,6 +200,7 @@ describe("FlatESLint", () => {
"- 'fixTypes' must be an array of any of \"directive\", \"problem\", \"suggestion\", and \"layout\".",
"- 'globInputPaths' must be a boolean.",
"- 'ignore' must be a boolean.",
"- 'ignorePatterns' must be an array of non-empty strings or null.",
"- 'overrideConfig' must be an object or null.",
"- 'overrideConfigFile' must be a non-empty string, null, or true.",
"- 'plugins' must be an object or null.",
Expand All @@ -207,6 +209,34 @@ describe("FlatESLint", () => {
);
});

it("should throw readable messages if 'ignorePatterns' is not an array of non-empty strings.", () => {
const invalidIgnorePatterns = [
() => {},
false,
{},
"",
"foo",
[[]],
[() => {}],
[false],
[{}],
[""],
["foo", ""],
["foo", "", "bar"],
["foo", false, "bar"]
];

invalidIgnorePatterns.forEach(ignorePatterns => {
assert.throws(
() => new FlatESLint({ ignorePatterns }),
new RegExp(escapeStringRegExp([
"Invalid Options:",
"- 'ignorePatterns' must be an array of non-empty strings or null."
].join("\n")), "u")
);
});
});

it("should throw readable messages if 'plugins' option contains empty key", () => {
assert.throws(
() => new FlatESLint({
Expand Down Expand Up @@ -3549,7 +3579,7 @@ describe("FlatESLint", () => {
const engine = new FlatESLint({
cwd,
overrideConfigFile: true,
ignorePatterns: "!node_modules/package/**"
ignorePatterns: ["!node_modules/package/**"]
});

const result = await engine.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js"));
Expand Down Expand Up @@ -4080,7 +4110,7 @@ describe("FlatESLint", () => {
const engine = new FlatESLint({
overrideConfigFile: true,
cwd: path.join(fixtureDir, "foo", "bar"),
ignorePatterns: "*/**", // ignore all subdirectories of `cwd`
ignorePatterns: ["*/**"], // ignore all subdirectories of `cwd`
overrideConfig: {
rules: {
eqeqeq: "warn"
Expand All @@ -4098,7 +4128,7 @@ describe("FlatESLint", () => {
const engine = new FlatESLint({
overrideConfigFile: true,
cwd: path.join(fixtureDir, "foo", "bar"),
ignorePatterns: "**"
ignorePatterns: ["**"]
});

const results = await engine.lintText("", { warnIgnored: true });
Expand All @@ -4111,7 +4141,7 @@ describe("FlatESLint", () => {
const engine = new FlatESLint({
overrideConfigFile: true,
cwd: getFixturePath(),
ignorePatterns: "passing*",
ignorePatterns: ["passing*"],
overrideConfig: {
rules: {
"no-undef": 2,
Expand Down Expand Up @@ -4225,7 +4255,7 @@ describe("FlatESLint", () => {
it("should ignore messages not related to a rule", async () => {
const engine = new FlatESLint({
overrideConfigFile: true,
ignorePatterns: "ignored.js",
ignorePatterns: ["ignored.js"],
overrideConfig: {
rules: {
"no-var": "warn"
Expand Down

0 comments on commit 0c415cd

Please sign in to comment.