Skip to content

Commit b006c58

Browse files
authored
Fix cache configuration property not being respected (#8599)
1 parent b764c23 commit b006c58

File tree

11 files changed

+152
-84
lines changed

11 files changed

+152
-84
lines changed

.changeset/loose-taxis-occur.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"stylelint": patch
3+
---
4+
5+
Fixed: `cache` configuration property not being respected

lib/__tests__/cli.test.mjs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,10 @@ jest.unstable_mockModule('stylelint-test-custom-formatter', () => ({ default: cu
3232
describe('buildCLI', () => {
3333
it('flags - default', () => {
3434
expect(buildCLI([]).flags).toEqual({
35-
allowEmptyInput: false,
36-
cache: false,
37-
color: false,
3835
computeEditInfo: false,
39-
disableDefaultIgnores: false,
40-
help: false,
41-
ignoreDisables: false,
4236
ignorePath: [],
4337
ignorePattern: [],
44-
printConfig: false,
45-
quiet: false,
46-
quietDeprecationWarnings: false,
47-
reportDescriptionlessDisables: false,
48-
reportInvalidScopeDisables: false,
49-
reportNeedlessDisables: false,
50-
reportUnscopedDisables: false,
51-
stdin: false,
5238
validate: true,
53-
version: false,
5439
});
5540
});
5641

@@ -61,6 +46,7 @@ describe('buildCLI', () => {
6146

6247
it('flags.cache', () => {
6348
expect(buildCLI(['--cache']).flags.cache).toBe(true);
49+
expect(buildCLI(['--no-cache']).flags.cache).toBe(false);
6450
});
6551

6652
it('flags.cacheLocation', () => {

lib/__tests__/standalone-cache.test.mjs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,14 +347,14 @@ describe('standalone cache uses a config file', () => {
347347

348348
const configFile = path.join(cwd, '.stylelintrc.json');
349349
const lintedFile = path.join(cwd, 'a.css');
350+
const expectedCacheFilePath = path.join(cwd, '.stylelintcache');
350351

351352
beforeEach(async () => {
352353
await writeFile(lintedFile, 'a {}');
353354
});
354355

355356
afterEach(async () => {
356-
await rm(configFile, { force: true });
357-
await rm(lintedFile, { force: true });
357+
await rm(cwd, { recursive: true, force: true });
358358
});
359359

360360
it('cache is discarded when a config file is changed', async () => {
@@ -382,6 +382,33 @@ describe('standalone cache uses a config file', () => {
382382

383383
expect(resultsNew[0].warnings).toHaveLength(1);
384384
});
385+
386+
it('enables cache in a config file', async () => {
387+
const options = { files: [lintedFile] };
388+
389+
await writeFile(configFile, JSON.stringify({ cache: true, rules: {} }));
390+
await standalone(options);
391+
392+
expect(existsSync(expectedCacheFilePath)).toBe(true);
393+
});
394+
395+
it('disables cache when the option precedes, regardless of a config file', async () => {
396+
const options = { files: [lintedFile], cache: false };
397+
398+
await writeFile(configFile, JSON.stringify({ cache: true, rules: {} }));
399+
await standalone(options);
400+
401+
expect(existsSync(expectedCacheFilePath)).toBe(false);
402+
});
403+
404+
it('disables cache when the config precedes, regardless of a config file', async () => {
405+
const config = { files: [lintedFile], config: { cache: false, rules: {} } };
406+
407+
await writeFile(configFile, JSON.stringify({ cache: true, rules: {} }));
408+
await standalone(config);
409+
410+
expect(existsSync(expectedCacheFilePath)).toBe(false);
411+
});
385412
});
386413

387414
describe('standalone cache uses cacheStrategy', () => {

lib/__tests__/standalone.test.mjs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,16 +212,26 @@ describe('standalone with nonexistent-file', () => {
212212
expect(errored).toBe(false);
213213
expect(report).toBe('[]');
214214
});
215-
});
216215

217-
it('standalone ignoring passed "allowEmptyInput: false" option', async () => {
218-
const { errored } = await standalone({
219-
files: `${fixturesPath}/nonexistent-file.css`,
220-
configFile: `${fixturesPath}/config-allow-empty-input.json`,
221-
allowEmptyInput: false,
216+
it('allowEmptyInput disabled in options, regardless that it is enabled in config', async () => {
217+
await expect(
218+
standalone({
219+
files: `${fixturesPath}/nonexistent-file.css`,
220+
config: { ...configBlockNoEmpty, allowEmptyInput: true },
221+
allowEmptyInput: false,
222+
}),
223+
).rejects.toThrow(NoFilesFoundError);
222224
});
223225

224-
expect(errored).toBe(false);
226+
it('allowEmptyInput disabled in options, regardless that it is enabled in config file', async () => {
227+
await expect(
228+
standalone({
229+
files: `${fixturesPath}/nonexistent-file.css`,
230+
configFile: `${fixturesPath}/config-allow-empty-input.json`,
231+
allowEmptyInput: false,
232+
}),
233+
).rejects.toThrow(NoFilesFoundError);
234+
});
225235
});
226236

227237
describe('standalone passing code with syntax error', () => {

lib/cli.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,9 @@ export function buildCLI(argv) {
679679
// See also https://github.com/sindresorhus/meow/blob/v12.0.1/source/validate.js#L75
680680
allowUnknownFlags: true,
681681

682+
// NOTE: If CLI flags are unspecified (e.g., `--cache` nor `--no-cache`), we want to fall back to config properties (e.g., `cache`).
683+
booleanDefault: undefined,
684+
682685
importMeta: import.meta,
683686
});
684687
}

lib/standalone.cjs

Lines changed: 9 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/standalone.mjs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ import getFormatter from './utils/getFormatter.mjs';
2222
import lintSource from './lintSource.mjs';
2323
import normalizeFixMode from './utils/normalizeFixMode.mjs';
2424
import prepareReturnValue from './prepareReturnValue.mjs';
25+
import resolveOptionValue from './utils/resolveOptionValue.mjs';
2526

2627
const ALWAYS_IGNORED_GLOBS = ['**/node_modules/**'];
2728

28-
/** @import {Formatter, FormatterType} from 'stylelint' */
29+
/** @import {InternalApi, LintResult} from 'stylelint' */
2930

3031
/**
3132
* @type {import('stylelint').PublicApi['lint']}
@@ -84,6 +85,8 @@ export default async function standalone({
8485
}
8586

8687
const stylelint = createStylelint({
88+
allowEmptyInput,
89+
cache,
8790
cacheLocation,
8891
cacheStrategy,
8992
config,
@@ -106,8 +109,6 @@ export default async function standalone({
106109
validate,
107110
});
108111

109-
/** @type {Formatter} */
110-
111112
/** @see https://github.com/stylelint/stylelint/issues/7447 */
112113
if (!quietDeprecationWarnings && formatter === 'github') {
113114
emitDeprecationWarning(
@@ -196,8 +197,7 @@ export default async function standalone({
196197
fileList = fileList.concat(ALWAYS_IGNORED_GLOBS.map((glob) => `!${glob}`));
197198
}
198199

199-
// do not cache if config is explicitly overridden by option
200-
const useCache = cache ?? config?.cache ?? false;
200+
const useCache = await resolveOptionValue({ stylelint, name: 'cache', default: false });
201201

202202
if (!useCache) {
203203
stylelint._fileCache.destroy();
@@ -283,7 +283,7 @@ export default async function standalone({
283283
});
284284

285285
stylelintResults = await Promise.all(getStylelintResults);
286-
} else if (allowEmptyInput || config?.allowEmptyInput || (await canAllowEmptyInput(stylelint))) {
286+
} else if (await resolveOptionValue({ stylelint, name: 'allowEmptyInput', default: false })) {
287287
stylelintResults = await Promise.all([]);
288288
} else if (filePathsLengthBeforeIgnore) {
289289
// All input files ignored
@@ -313,7 +313,7 @@ export default async function standalone({
313313
* @import {CssSyntaxError} from 'stylelint'
314314
*
315315
* @param {unknown} error
316-
* @returns {import('stylelint').LintResult}
316+
* @returns {LintResult}
317317
*/
318318
function handleError(error) {
319319
if (error instanceof Error && error.name === 'CssSyntaxError') {
@@ -324,18 +324,8 @@ function handleError(error) {
324324
}
325325

326326
/**
327-
* @param {import('stylelint').InternalApi} stylelint
328-
* @returns {Promise<boolean>}
329-
*/
330-
async function canAllowEmptyInput(stylelint) {
331-
const config = await getConfigForFile({ stylelint });
332-
333-
return Boolean(config?.config?.allowEmptyInput);
334-
}
335-
336-
/**
337-
* @param {import('stylelint').InternalApi} stylelint
338-
* @param {import('stylelint').LintResult} stylelintResult
327+
* @param {InternalApi} stylelint
328+
* @param {LintResult} stylelintResult
339329
* @param {string} [filePath]
340330
* @returns {Promise<void>}
341331
*/

lib/utils/getFormatter.cjs

Lines changed: 6 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/utils/getFormatter.mjs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
1-
import dynamicImport from './dynamicImport.mjs';
21
import { existsSync } from 'node:fs';
2+
import { resolve } from 'node:path';
3+
4+
import dynamicImport from './dynamicImport.mjs';
35
import formatters from '../formatters/index.mjs';
4-
import getConfigForFile from '../getConfigForFile.mjs';
56
import getFormatterOptionsText from './getFormatterOptionsText.mjs';
6-
import { resolve } from 'node:path';
7+
import resolveOptionValue from './resolveOptionValue.mjs';
78

8-
/** @import {Formatter, InternalApi} from 'stylelint' */
9+
/** @import {Formatter, FormatterType, InternalApi} from 'stylelint' */
910

1011
/**
1112
* @param {InternalApi} stylelint
1213
* @returns {Promise<Formatter>}
1314
*/
1415
export default async function getFormatter(stylelint) {
15-
let formatter = stylelint._options.formatter;
16-
17-
if (!formatter) {
18-
const config = await getConfigForFile({ stylelint, failIfNoConfig: false });
19-
20-
formatter = config?.config.formatter;
21-
}
16+
/** @type {FormatterType | undefined} */
17+
let formatter = await resolveOptionValue({ stylelint, name: 'formatter' });
2218

2319
if (typeof formatter === 'string') {
2420
let formatterFunction = formatters[formatter];

lib/utils/resolveOptionValue.cjs

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)