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

Throw error on non-existent files unless allow-empty-input is enabled #3965

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
3 changes: 2 additions & 1 deletion flow-typed/stylelint.js
Expand Up @@ -147,5 +147,6 @@ export type stylelint$standaloneOptions = {
customSyntax?: string,
formatter?: "compact" | "json" | "string" | "unix" | "verbose" | Function,
disableDefaultIgnores?: boolean,
fix?: boolean
fix?: boolean,
allowEmptyInput: boolean
};
59 changes: 38 additions & 21 deletions lib/__tests__/ignore.test.js
@@ -1,5 +1,6 @@
"use strict";

const NoFilesFoundError = require("../utils/noFilesFoundError");
const path = require("path");
const standalone = require("../standalone");

Expand Down Expand Up @@ -191,8 +192,10 @@ describe("extending config with ignoreFiles glob ignoring one by negation", () =
});

describe("specified `ignorePath` file ignoring one file", () => {
let results;
const files = [`${fixturesPath}/empty-block.css`];
const noFilesErrorMessage = new NoFilesFoundError(files);
let actualCwd;
let errorMessage;

beforeAll(() => {
actualCwd = process.cwd();
Expand All @@ -205,24 +208,28 @@ describe("specified `ignorePath` file ignoring one file", () => {

beforeEach(() => {
return standalone({
files: [`${fixturesPath}/empty-block.css`],
files,
config: {
rules: {
"block-no-empty": true
}
},
ignorePath: path.join(__dirname, "fixtures/ignore.txt")
}).then(data => (results = data.results));
}).catch(actualError => {
errorMessage = actualError;
});
});

it("no files read", () => {
expect(results).toHaveLength(0);
expect(errorMessage).toEqual(noFilesErrorMessage);
});
});

describe("specified `ignorePattern` file ignoring one file", () => {
let results;
const files = [`${fixturesPath}/empty-block.css`];
const noFilesErrorMessage = new NoFilesFoundError(files);
let actualCwd;
let errorMessage;

beforeAll(() => {
actualCwd = process.cwd();
Expand All @@ -235,24 +242,31 @@ describe("specified `ignorePattern` file ignoring one file", () => {

beforeEach(() => {
return standalone({
files: [`${fixturesPath}/empty-block.css`],
files,
config: {
rules: {
"block-no-empty": true
}
},
ignorePattern: "fixtures/empty-block.css"
}).then(data => (results = data.results));
}).catch(actualError => {
errorMessage = actualError;
});
});

it("no files read", () => {
expect(results).toHaveLength(0);
expect(errorMessage).toEqual(noFilesErrorMessage);
});
});

describe("specified `ignorePattern` file ignoring two files", () => {
let results;
const files = [
`${fixturesPath}/empty-block.css`,
`${fixturesPath}/no-syntax-error.css`
];
const noFilesErrorMessage = new NoFilesFoundError(files);
let actualCwd;
let errorMessage;

beforeAll(() => {
actualCwd = process.cwd();
Expand All @@ -265,10 +279,7 @@ describe("specified `ignorePattern` file ignoring two files", () => {

beforeEach(() => {
return standalone({
files: [
`${fixturesPath}/empty-block.css`,
`${fixturesPath}/no-syntax-error.css`
],
files,
config: {
rules: {
"block-no-empty": true
Expand All @@ -278,11 +289,13 @@ describe("specified `ignorePattern` file ignoring two files", () => {
"fixtures/empty-block.css",
"fixtures/no-syntax-error.css"
]
}).then(data => (results = data.results));
}).catch(actualError => {
errorMessage = actualError;
});
});

it("no files read", () => {
expect(results).toHaveLength(0);
expect(errorMessage).toEqual(noFilesErrorMessage);
});
});

Expand Down Expand Up @@ -416,9 +429,11 @@ describe("using codeFilename and ignoreFiles with configBasedir", () => {
});

describe("file in node_modules", () => {
const files = [`${fixturesPath}/node_modules/test.css`];
const noFilesErrorMessage = new NoFilesFoundError(files);
const lint = () =>
standalone({
files: [`${fixturesPath}/node_modules/test.css`],
files,
config: {
rules: {
"block-no-empty": true
Expand All @@ -427,16 +442,18 @@ describe("file in node_modules", () => {
});

it("is ignored", () => {
return lint().then(output => {
expect(output.results).toHaveLength(0);
return lint().catch(actualError => {
expect(actualError).toEqual(noFilesErrorMessage);
});
});
});

describe("file in bower_components", () => {
const files = [`${fixturesPath}/bower_components/test.css`];
const noFilesErrorMessage = new NoFilesFoundError(files);
const lint = () =>
standalone({
files: [`${fixturesPath}/bower_components/test.css`],
files,
config: {
rules: {
"block-no-empty": true
Expand All @@ -445,8 +462,8 @@ describe("file in bower_components", () => {
});

it("is ignored", () => {
return lint().then(output => {
expect(output.results).toHaveLength(0);
return lint().catch(actualError => {
expect(actualError).toEqual(noFilesErrorMessage);
});
});
});
Expand Down
18 changes: 16 additions & 2 deletions lib/__tests__/standalone.test.js
@@ -1,6 +1,7 @@
"use strict";

const configBlockNoEmpty = require("./fixtures/config-block-no-empty");
const NoFilesFoundError = require("../utils/noFilesFoundError");
const path = require("path");
const standalone = require("../standalone");

Expand Down Expand Up @@ -114,10 +115,23 @@ it("standalone without input css and file(s) should throw error", () => {
);
});

it("standalone with non-existent-file quietly exits", () => {
it("standalone with non-existent-file throws an error", () => {
const files = `${fixturesPath}/non-existent-file.css`;
const expectedError = new NoFilesFoundError(files);

return standalone({
files: `${fixturesPath}/non-existent-file.css`,
files,
config: configBlockNoEmpty
}).catch(actualError => {
expect(actualError).toEqual(expectedError);
});
});

it("standalone with non-existent-file and allowEmptyInput enabled quietly exits", () => {
return standalone({
files: `${fixturesPath}/non-existent-file.css`,
config: configBlockNoEmpty,
allowEmptyInput: true
}).then(linted => {
expect(typeof linted.output).toBe("string");
expect(linted.results).toHaveLength(0);
Expand Down
14 changes: 12 additions & 2 deletions lib/cli.js
Expand Up @@ -125,7 +125,8 @@ const EXIT_CODE_ERROR = 2;
stdinFilename: any,
syntax: any,
v: string,
version: string
version: string,
allowEmptyInput: boolean
},
input: any,
help: any,
Expand Down Expand Up @@ -153,7 +154,8 @@ const EXIT_CODE_ERROR = 2;
maxWarnings?: any,
syntax?: any,
disableDefaultIgnores?: any,
ignorePattern?: any
ignorePattern?: any,
allowEmptyInput?: boolean
}*/

const meowOptions /*: meowOptionsType*/ = {
Expand Down Expand Up @@ -278,6 +280,10 @@ const meowOptions /*: meowOptionsType*/ = {
--version, -v

Show the currently installed version of stylelint.

--allow-empty-input

When glob pattern matches no files, the process will exit without throwing an error.
`,
flags: {
cache: {
Expand Down Expand Up @@ -478,6 +484,10 @@ module.exports = (argv /*: string[]*/) /*: Promise<void>|void*/ => {
return;
}

if (cli.flags.allowEmptyInput) {
optionsBase.allowEmptyInput = cli.flags.allowEmptyInput;
}

return Promise.resolve()
.then(() => {
// Add input/code into options
Expand Down
6 changes: 6 additions & 0 deletions lib/standalone.js
Expand Up @@ -14,6 +14,7 @@ const globby /*: Function*/ = require("globby");
const hash = require("./utils/hash");
const ignore = require("ignore");
const needlessDisables /*: Function*/ = require("./needlessDisables");
const NoFilesFoundError = require("./utils/noFilesFoundError");
const path = require("path");
const pify = require("pify");
const pkg = require("../package.json");
Expand Down Expand Up @@ -42,6 +43,7 @@ module.exports = function(
const reportNeedlessDisables = options.reportNeedlessDisables;
const maxWarnings = options.maxWarnings;
const syntax = options.syntax;
const allowEmptyInput = options.allowEmptyInput || false;
const useCache = options.cache || false;
let fileCache;
const startTime = Date.now();
Expand Down Expand Up @@ -198,6 +200,10 @@ module.exports = function(
);

if (!filePaths.length) {
if (!allowEmptyInput) {
throw new NoFilesFoundError(fileList);
}

return Promise.all([]);
}

Expand Down
17 changes: 17 additions & 0 deletions lib/utils/noFilesFoundError.js
@@ -0,0 +1,17 @@
"use strict";

class NoFilesFoundError extends Error {
constructor(fileList) {
super();

if (typeof fileList === "string") {
fileList = [fileList];
}

const pattern = fileList.filter(i => !i.startsWith("!")).join(", ");

this.message = `No files matching the pattern "${pattern}" were found.`;
}
}

module.exports = NoFilesFoundError;