From 7c7e0c17077d6ce35c3c6f27d248ea4899ec6249 Mon Sep 17 00:00:00 2001 From: kimulaco Date: Sun, 2 Oct 2022 23:54:15 +0900 Subject: [PATCH 1/7] feat: Add postcssResult to FileCache --- lib/__tests__/standalone-cache.test.js | 24 ++++++++++++++++++++ lib/lintSource.js | 31 +++++++++++++++++++++----- lib/utils/FileCache.js | 31 +++++++++++++++++++++++++- types/stylelint/index.d.ts | 2 ++ 4 files changed, 81 insertions(+), 7 deletions(-) diff --git a/lib/__tests__/standalone-cache.test.js b/lib/__tests__/standalone-cache.test.js index 45c629041c..c592fa699c 100644 --- a/lib/__tests__/standalone-cache.test.js +++ b/lib/__tests__/standalone-cache.test.js @@ -83,6 +83,30 @@ describe('standalone cache', () => { expect(cache.getKey(newFileDest)).toBeTruthy(); }); + it('returns result also cached warning file', async () => { + await fs.copyFile(invalidFile, newFileDest); + + const { results } = await standalone( + getConfig({ + config: { + rules: { 'block-no-empty': [true, { severity: 'warning' }] }, + }, + }), + ); + + expect(results.find((file) => file.source === newFileDest).warnings).toHaveLength(1); + + const { results: resultsNew } = await standalone( + getConfig({ + config: { + rules: { 'block-no-empty': [true, { severity: 'warning' }] }, + }, + }), + ); + + expect(resultsNew.find((file) => file.source === newFileDest).warnings).toHaveLength(1); + }); + it('all files are linted on config change', async () => { await fs.copyFile(validFile, newFileDest); diff --git a/lib/lintSource.js b/lib/lintSource.js index bd101d4a61..6400a9ccca 100644 --- a/lib/lintSource.js +++ b/lib/lintSource.js @@ -69,12 +69,12 @@ module.exports = async function lintSource(stylelint, options = {}) { if (options.cache) { stylelint._fileCache.calcHashOfConfig(config); - if (options.filePath && !stylelint._fileCache.hasFileChanged(options.filePath)) { - return existingPostcssResult - ? Object.assign(existingPostcssResult, { - stylelint: createEmptyStylelintPostcssResult(), - }) - : createEmptyPostcssResult(inputFilePath); + if (inputFilePath && !stylelint._fileCache.hasFileChanged(inputFilePath)) { + const cachedPostcssResult = stylelint._fileCache.getPostcssResult(inputFilePath); + + if (cachedPostcssResult) { + return createCachedPostcssResult(cachedPostcssResult, inputFilePath); + } } } @@ -102,6 +102,10 @@ module.exports = async function lintSource(stylelint, options = {}) { await lintPostcssResult(stylelint._options, stylelintPostcssResult, config); + if (options.cache && inputFilePath) { + stylelint._fileCache.setPostcssResult(inputFilePath, stylelintPostcssResult); + } + return stylelintPostcssResult; }; @@ -136,3 +140,18 @@ function createEmptyPostcssResult(filePath) { warn: () => {}, }; } + +/** + * @param {PostcssResult} postcssResult + * @param {string} [filePath] + * @returns {PostcssResult} + */ +function createCachedPostcssResult(postcssResult, filePath) { + postcssResult.root.source = { + ...(postcssResult.root.source || {}), + input: { file: filePath }, + }; + postcssResult.stylelint.ignored = true; + + return postcssResult; +} diff --git a/lib/utils/FileCache.js b/lib/utils/FileCache.js index c599e6b82a..9e2957a619 100644 --- a/lib/utils/FileCache.js +++ b/lib/utils/FileCache.js @@ -13,7 +13,8 @@ const CACHE_STRATEGY_CONTENT = 'content'; const DEFAULT_CACHE_LOCATION = './.stylelintcache'; const DEFAULT_CACHE_STRATEGY = CACHE_STRATEGY_METADATA; -/** @typedef {import('file-entry-cache').FileDescriptor["meta"] & { hashOfConfig?: string }} CacheMetadata */ +/** @typedef {import('stylelint').PostcssResult} PostcssResult */ +/** @typedef {import('file-entry-cache').FileDescriptor["meta"] & { hashOfConfig?: string, postcssResult?: PostcssResult }} CacheMetadata */ class FileCache { constructor( @@ -72,6 +73,34 @@ class FileCache { return changed; } + /** + * @param {string} absoluteFilepath + * @return {PostcssResult|undefined} + */ + getPostcssResult(absoluteFilepath) { + const descriptor = this._fileCache.getFileDescriptor(absoluteFilepath); + /** @type {CacheMetadata} */ + const meta = descriptor.meta || {}; + + return meta.postcssResult; + } + + /** + * @param {string} absoluteFilepath + * @param {PostcssResult} postcssResult + */ + setPostcssResult(absoluteFilepath, postcssResult) { + const descriptor = this._fileCache.getFileDescriptor(absoluteFilepath); + /** @type {CacheMetadata} */ + const meta = descriptor.meta || {}; + + if (meta.hashOfConfig !== this._hashOfConfig) { + meta.hashOfConfig = this._hashOfConfig; + } + + meta.postcssResult = postcssResult; + } + reconcile() { this._fileCache.reconcile(); } diff --git a/types/stylelint/index.d.ts b/types/stylelint/index.d.ts index 940ab88106..b474b74f1b 100644 --- a/types/stylelint/index.d.ts +++ b/types/stylelint/index.d.ts @@ -94,6 +94,8 @@ declare module 'stylelint' { reconcile: () => void; destroy: () => void; removeEntry: (absoluteFilepath: string) => void; + setPostcssResult: (absoluteFilepath: string, result: PostcssResult) => void; + getPostcssResult: (absoluteFilepath: string) => PostcssResult | undefined; }; export type StylelintPostcssResult = { From 9f3f46350aee4712f22100019606e0d3de07cb75 Mon Sep 17 00:00:00 2001 From: kimulaco Date: Mon, 3 Oct 2022 07:50:47 +0900 Subject: [PATCH 2/7] chore: Refactor `standalone-cache.test.js` --- lib/__tests__/standalone-cache.test.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/__tests__/standalone-cache.test.js b/lib/__tests__/standalone-cache.test.js index c592fa699c..bb178a8bc1 100644 --- a/lib/__tests__/standalone-cache.test.js +++ b/lib/__tests__/standalone-cache.test.js @@ -14,6 +14,12 @@ const isChanged = (file, targetFilePath) => { return file.source === targetFilePath && !file.ignored; }; +const getWarnings = (results, targetFilePath) => { + const result = results.find((file) => file.source === targetFilePath); + + return result ? result.warnings || [] : []; +}; + const fixturesPath = path.join(__dirname, 'fixtures'); const invalidFile = path.join(fixturesPath, 'empty-block.css'); const syntaxErrorFile = path.join(fixturesPath, 'syntax_error.css'); @@ -83,9 +89,11 @@ describe('standalone cache', () => { expect(cache.getKey(newFileDest)).toBeTruthy(); }); - it('returns result also cached warning file', async () => { + it('return results of cached warning file', async () => { + await removeFile(expectedCacheFilePath); await fs.copyFile(invalidFile, newFileDest); + // Return warnings when no cache const { results } = await standalone( getConfig({ config: { @@ -94,8 +102,10 @@ describe('standalone cache', () => { }), ); - expect(results.find((file) => file.source === newFileDest).warnings).toHaveLength(1); + expect(getWarnings(results, newFileDest)).toHaveLength(1); + expect(results.some((file) => isChanged(file, newFileDest))).toBe(true); + // Return cached warnings when re-linted const { results: resultsNew } = await standalone( getConfig({ config: { @@ -104,7 +114,8 @@ describe('standalone cache', () => { }), ); - expect(resultsNew.find((file) => file.source === newFileDest).warnings).toHaveLength(1); + expect(getWarnings(resultsNew, newFileDest)).toHaveLength(1); + expect(resultsNew.some((file) => isChanged(file, newFileDest))).toBe(false); }); it('all files are linted on config change', async () => { From aa28b1af1a85acc6123a91b89507b0df66415c15 Mon Sep 17 00:00:00 2001 From: kimulaco Date: Wed, 5 Oct 2022 22:29:38 +0900 Subject: [PATCH 3/7] Revert "chore: Refactor `standalone-cache.test.js`" This reverts commit 9f3f46350aee4712f22100019606e0d3de07cb75. --- lib/__tests__/standalone-cache.test.js | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/lib/__tests__/standalone-cache.test.js b/lib/__tests__/standalone-cache.test.js index bb178a8bc1..c592fa699c 100644 --- a/lib/__tests__/standalone-cache.test.js +++ b/lib/__tests__/standalone-cache.test.js @@ -14,12 +14,6 @@ const isChanged = (file, targetFilePath) => { return file.source === targetFilePath && !file.ignored; }; -const getWarnings = (results, targetFilePath) => { - const result = results.find((file) => file.source === targetFilePath); - - return result ? result.warnings || [] : []; -}; - const fixturesPath = path.join(__dirname, 'fixtures'); const invalidFile = path.join(fixturesPath, 'empty-block.css'); const syntaxErrorFile = path.join(fixturesPath, 'syntax_error.css'); @@ -89,11 +83,9 @@ describe('standalone cache', () => { expect(cache.getKey(newFileDest)).toBeTruthy(); }); - it('return results of cached warning file', async () => { - await removeFile(expectedCacheFilePath); + it('returns result also cached warning file', async () => { await fs.copyFile(invalidFile, newFileDest); - // Return warnings when no cache const { results } = await standalone( getConfig({ config: { @@ -102,10 +94,8 @@ describe('standalone cache', () => { }), ); - expect(getWarnings(results, newFileDest)).toHaveLength(1); - expect(results.some((file) => isChanged(file, newFileDest))).toBe(true); + expect(results.find((file) => file.source === newFileDest).warnings).toHaveLength(1); - // Return cached warnings when re-linted const { results: resultsNew } = await standalone( getConfig({ config: { @@ -114,8 +104,7 @@ describe('standalone cache', () => { }), ); - expect(getWarnings(resultsNew, newFileDest)).toHaveLength(1); - expect(resultsNew.some((file) => isChanged(file, newFileDest))).toBe(false); + expect(resultsNew.find((file) => file.source === newFileDest).warnings).toHaveLength(1); }); it('all files are linted on config change', async () => { From db190028f17a2283e1f4d9ac53ea28559dfc1701 Mon Sep 17 00:00:00 2001 From: kimulaco Date: Wed, 5 Oct 2022 22:29:46 +0900 Subject: [PATCH 4/7] Revert "feat: Add postcssResult to FileCache" This reverts commit 7c7e0c17077d6ce35c3c6f27d248ea4899ec6249. --- lib/__tests__/standalone-cache.test.js | 24 -------------------- lib/lintSource.js | 31 +++++--------------------- lib/utils/FileCache.js | 31 +------------------------- types/stylelint/index.d.ts | 2 -- 4 files changed, 7 insertions(+), 81 deletions(-) diff --git a/lib/__tests__/standalone-cache.test.js b/lib/__tests__/standalone-cache.test.js index c592fa699c..45c629041c 100644 --- a/lib/__tests__/standalone-cache.test.js +++ b/lib/__tests__/standalone-cache.test.js @@ -83,30 +83,6 @@ describe('standalone cache', () => { expect(cache.getKey(newFileDest)).toBeTruthy(); }); - it('returns result also cached warning file', async () => { - await fs.copyFile(invalidFile, newFileDest); - - const { results } = await standalone( - getConfig({ - config: { - rules: { 'block-no-empty': [true, { severity: 'warning' }] }, - }, - }), - ); - - expect(results.find((file) => file.source === newFileDest).warnings).toHaveLength(1); - - const { results: resultsNew } = await standalone( - getConfig({ - config: { - rules: { 'block-no-empty': [true, { severity: 'warning' }] }, - }, - }), - ); - - expect(resultsNew.find((file) => file.source === newFileDest).warnings).toHaveLength(1); - }); - it('all files are linted on config change', async () => { await fs.copyFile(validFile, newFileDest); diff --git a/lib/lintSource.js b/lib/lintSource.js index 6400a9ccca..bd101d4a61 100644 --- a/lib/lintSource.js +++ b/lib/lintSource.js @@ -69,12 +69,12 @@ module.exports = async function lintSource(stylelint, options = {}) { if (options.cache) { stylelint._fileCache.calcHashOfConfig(config); - if (inputFilePath && !stylelint._fileCache.hasFileChanged(inputFilePath)) { - const cachedPostcssResult = stylelint._fileCache.getPostcssResult(inputFilePath); - - if (cachedPostcssResult) { - return createCachedPostcssResult(cachedPostcssResult, inputFilePath); - } + if (options.filePath && !stylelint._fileCache.hasFileChanged(options.filePath)) { + return existingPostcssResult + ? Object.assign(existingPostcssResult, { + stylelint: createEmptyStylelintPostcssResult(), + }) + : createEmptyPostcssResult(inputFilePath); } } @@ -102,10 +102,6 @@ module.exports = async function lintSource(stylelint, options = {}) { await lintPostcssResult(stylelint._options, stylelintPostcssResult, config); - if (options.cache && inputFilePath) { - stylelint._fileCache.setPostcssResult(inputFilePath, stylelintPostcssResult); - } - return stylelintPostcssResult; }; @@ -140,18 +136,3 @@ function createEmptyPostcssResult(filePath) { warn: () => {}, }; } - -/** - * @param {PostcssResult} postcssResult - * @param {string} [filePath] - * @returns {PostcssResult} - */ -function createCachedPostcssResult(postcssResult, filePath) { - postcssResult.root.source = { - ...(postcssResult.root.source || {}), - input: { file: filePath }, - }; - postcssResult.stylelint.ignored = true; - - return postcssResult; -} diff --git a/lib/utils/FileCache.js b/lib/utils/FileCache.js index 9e2957a619..c599e6b82a 100644 --- a/lib/utils/FileCache.js +++ b/lib/utils/FileCache.js @@ -13,8 +13,7 @@ const CACHE_STRATEGY_CONTENT = 'content'; const DEFAULT_CACHE_LOCATION = './.stylelintcache'; const DEFAULT_CACHE_STRATEGY = CACHE_STRATEGY_METADATA; -/** @typedef {import('stylelint').PostcssResult} PostcssResult */ -/** @typedef {import('file-entry-cache').FileDescriptor["meta"] & { hashOfConfig?: string, postcssResult?: PostcssResult }} CacheMetadata */ +/** @typedef {import('file-entry-cache').FileDescriptor["meta"] & { hashOfConfig?: string }} CacheMetadata */ class FileCache { constructor( @@ -73,34 +72,6 @@ class FileCache { return changed; } - /** - * @param {string} absoluteFilepath - * @return {PostcssResult|undefined} - */ - getPostcssResult(absoluteFilepath) { - const descriptor = this._fileCache.getFileDescriptor(absoluteFilepath); - /** @type {CacheMetadata} */ - const meta = descriptor.meta || {}; - - return meta.postcssResult; - } - - /** - * @param {string} absoluteFilepath - * @param {PostcssResult} postcssResult - */ - setPostcssResult(absoluteFilepath, postcssResult) { - const descriptor = this._fileCache.getFileDescriptor(absoluteFilepath); - /** @type {CacheMetadata} */ - const meta = descriptor.meta || {}; - - if (meta.hashOfConfig !== this._hashOfConfig) { - meta.hashOfConfig = this._hashOfConfig; - } - - meta.postcssResult = postcssResult; - } - reconcile() { this._fileCache.reconcile(); } diff --git a/types/stylelint/index.d.ts b/types/stylelint/index.d.ts index 807c1b2f7c..1a12c44f81 100644 --- a/types/stylelint/index.d.ts +++ b/types/stylelint/index.d.ts @@ -93,8 +93,6 @@ declare module 'stylelint' { reconcile: () => void; destroy: () => void; removeEntry: (absoluteFilepath: string) => void; - setPostcssResult: (absoluteFilepath: string, result: PostcssResult) => void; - getPostcssResult: (absoluteFilepath: string) => PostcssResult | undefined; }; export type StylelintPostcssResult = { From ea81d29ee2c36ec65fa685b59edb9e6109e113aa Mon Sep 17 00:00:00 2001 From: kimulaco Date: Wed, 5 Oct 2022 21:49:12 +0900 Subject: [PATCH 5/7] Fix to discard cache also when warning --- lib/__tests__/standalone-cache.test.js | 24 ++++++++++++++++++++++++ lib/utils/report.js | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/__tests__/standalone-cache.test.js b/lib/__tests__/standalone-cache.test.js index 45c629041c..b7a16ab57b 100644 --- a/lib/__tests__/standalone-cache.test.js +++ b/lib/__tests__/standalone-cache.test.js @@ -119,6 +119,30 @@ describe('standalone cache', () => { expect(cache.getKey(newFileDest)).toBeUndefined(); }); + it('warning files are not cached', async () => { + await fs.copyFile(invalidFile, newFileDest); + + const { errored, results } = await standalone( + getConfig({ + config: { + rules: { 'block-no-empty': [true, { severity: 'warning' }] }, + }, + }), + ); + + expect(errored).toBe(true); + + // cache is discarded because config changed + expect(results.some((file) => isChanged(file, validFile))).toBe(true); + expect(results.some((file) => isChanged(file, newFileDest))).toBe(true); + + const { cache } = fCache.createFromFile(expectedCacheFilePath); + + expect(typeof cache.getKey(validFile)).toBe('object'); + expect(cache.getKey(validFile)).toBeTruthy(); + expect(cache.getKey(newFileDest)).toBeUndefined(); + }); + it('files with syntax errors are not cached', async () => { await fs.copyFile(syntaxErrorFile, newFileDest); diff --git a/lib/utils/report.js b/lib/utils/report.js index a84ae5e808..d215c6ded2 100644 --- a/lib/utils/report.js +++ b/lib/utils/report.js @@ -74,7 +74,7 @@ module.exports = function report(problem) { const severity = result.stylelint.ruleSeverities && result.stylelint.ruleSeverities[ruleName]; - if (!result.stylelint.stylelintError && severity === 'error') { + if (!result.stylelint.stylelintError && (severity === 'error' || severity === 'warning')) { result.stylelint.stylelintError = true; } From 8b5b626912fd447f45ff06617afe2faa3ca3e1f2 Mon Sep 17 00:00:00 2001 From: kimulaco Date: Wed, 5 Oct 2022 22:25:53 +0900 Subject: [PATCH 6/7] Add stylelintWarning to StylelintPostcssResult --- lib/__tests__/standalone-cache.test.js | 2 +- lib/lintPostcssResult.js | 1 + lib/lintSource.js | 1 + lib/standalone.js | 5 ++++- lib/utils/report.js | 6 +++++- types/stylelint/index.d.ts | 1 + 6 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/__tests__/standalone-cache.test.js b/lib/__tests__/standalone-cache.test.js index b7a16ab57b..7766a5f610 100644 --- a/lib/__tests__/standalone-cache.test.js +++ b/lib/__tests__/standalone-cache.test.js @@ -130,7 +130,7 @@ describe('standalone cache', () => { }), ); - expect(errored).toBe(true); + expect(errored).toBe(false); // cache is discarded because config changed expect(results.some((file) => isChanged(file, validFile))).toBe(true); diff --git a/lib/lintPostcssResult.js b/lib/lintPostcssResult.js index 23d0f75e5f..0cde1a0af9 100644 --- a/lib/lintPostcssResult.js +++ b/lib/lintPostcssResult.js @@ -20,6 +20,7 @@ function lintPostcssResult(stylelintOptions, postcssResult, config) { postcssResult.stylelint.customMessages = {}; postcssResult.stylelint.ruleMetadata = {}; postcssResult.stylelint.stylelintError = false; + postcssResult.stylelint.stylelintWarning = false; postcssResult.stylelint.quiet = config.quiet; postcssResult.stylelint.config = config; diff --git a/lib/lintSource.js b/lib/lintSource.js index bd101d4a61..01029a2070 100644 --- a/lib/lintSource.js +++ b/lib/lintSource.js @@ -116,6 +116,7 @@ function createEmptyStylelintPostcssResult() { disabledRanges: {}, ignored: true, stylelintError: false, + stylelintWarning: false, }; } diff --git a/lib/standalone.js b/lib/standalone.js index b74659ab7d..5f2781ab91 100644 --- a/lib/standalone.js +++ b/lib/standalone.js @@ -216,7 +216,10 @@ async function standalone({ cache: useCache, }); - if (postcssResult.stylelint.stylelintError && useCache) { + if ( + (postcssResult.stylelint.stylelintError || postcssResult.stylelint.stylelintWarning) && + useCache + ) { debug(`${absoluteFilepath} contains linting errors and will not be cached.`); stylelint._fileCache.removeEntry(absoluteFilepath); } diff --git a/lib/utils/report.js b/lib/utils/report.js index d215c6ded2..befcd739c5 100644 --- a/lib/utils/report.js +++ b/lib/utils/report.js @@ -74,10 +74,14 @@ module.exports = function report(problem) { const severity = result.stylelint.ruleSeverities && result.stylelint.ruleSeverities[ruleName]; - if (!result.stylelint.stylelintError && (severity === 'error' || severity === 'warning')) { + if (!result.stylelint.stylelintError && severity === 'error') { result.stylelint.stylelintError = true; } + if (!result.stylelint.stylelintWarning && severity === 'warning') { + result.stylelint.stylelintWarning = true; + } + /** @type {import('stylelint').WarningOptions} */ const warningProperties = { severity, diff --git a/types/stylelint/index.d.ts b/types/stylelint/index.d.ts index 1a12c44f81..bb1c7681ab 100644 --- a/types/stylelint/index.d.ts +++ b/types/stylelint/index.d.ts @@ -104,6 +104,7 @@ declare module 'stylelint' { disabledWarnings?: DisabledWarning[]; ignored?: boolean; stylelintError?: boolean; + stylelintWarning?: boolean; disableWritingFix?: boolean; config?: Config; ruleDisableFix?: boolean; From a85f2e1b0c60f36a22c10b4cef91da282620e480 Mon Sep 17 00:00:00 2001 From: kimulaco Date: Wed, 5 Oct 2022 23:45:59 +0900 Subject: [PATCH 7/7] Create changelog --- .changeset/metal-pillows-report.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/metal-pillows-report.md diff --git a/.changeset/metal-pillows-report.md b/.changeset/metal-pillows-report.md new file mode 100644 index 0000000000..4e217cb085 --- /dev/null +++ b/.changeset/metal-pillows-report.md @@ -0,0 +1,5 @@ +--- +"stylelint": patch +--- + +Fixed: false negatives on second run for cache and `severity` option