From 8ef36c13a0b16d7cf5082db971cb8e16f46c96fd Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 9 Oct 2026 19:05:27 +0800 Subject: [PATCH 1/3] fix: format files after incomplete lint fixes --- packages/rstack/src/cli/commands.ts | 3 -- packages/rstack/tests/cli/check.test.ts | 66 +++++++++++++++++++------ website/docs/en/guide/cli/check.mdx | 2 +- website/docs/zh/guide/cli/check.mdx | 2 +- 4 files changed, 53 insertions(+), 20 deletions(-) diff --git a/packages/rstack/src/cli/commands.ts b/packages/rstack/src/cli/commands.ts index c42f1cc2..5fc8cd68 100644 --- a/packages/rstack/src/cli/commands.ts +++ b/packages/rstack/src/cli/commands.ts @@ -189,9 +189,6 @@ async function runCheckCLI(args: string[]): Promise { ]); const lintExitCode = Number(process.exitCode ?? 0); - if (values.fix && lintExitCode !== 0) { - return; - } // Rslint loads its one-shot config through Node's module cache. Import the // same URL to read the Rstack config exported for the following fmt phase. diff --git a/packages/rstack/tests/cli/check.test.ts b/packages/rstack/tests/cli/check.test.ts index d7b0e3f4..44789d1a 100644 --- a/packages/rstack/tests/cli/check.test.ts +++ b/packages/rstack/tests/cli/check.test.ts @@ -192,30 +192,66 @@ test.each([ }, ); -test('preserves a formatter error exit code after lint fails', () => { - writeLintConfig(); - writeProjectFile('src/index.js', 'debugger;\n'); - writeProjectFile('src/broken.json', '{ "value": }'); +test.each([false, true])( + 'preserves a formatter error exit code after lint fails (fix: %s)', + (fix) => { + writeLintConfig(); + writeProjectFile('src/index.js', 'debugger;\n'); + writeProjectFile('src/broken.json', '{ "value": }'); + + const result = runCheck([...(fix ? ['--fix'] : []), 'src']); + + expect(result.status).toBe(2); + expect(`${result.stdout}\n${result.stderr}`).toContain( + "Unexpected 'debugger' statement", + ); + expect(result.stderr).toContain('broken.json'); + }, +); + +test('formats lint fixes even when unfixable errors remain', () => { + writeProjectFile( + 'rstack.config.ts', + `import { define } from 'rstack'; +define.lint([{ + files: ['**/*.js'], + rules: { curly: 'error', 'no-debugger': 'error' }, +}]); +`, + ); + writeProjectFile('src/index.js', 'debugger;let value=true;if(value) value++'); + writeProjectFile( + 'src/unselected.js', + 'debugger;let value=true;if(value) value++', + ); - const result = runCheck(['src']); + const result = runCheck(['--fix', 'src/index.js']); - expect(result.status).toBe(2); + expect(result.status).toBe(1); expect(`${result.stdout}\n${result.stderr}`).toContain( "Unexpected 'debugger' statement", ); - expect(result.stderr).toContain('broken.json'); + expect(result.stdout).toContain('Formatting completed in'); + expect(readProjectFile('src/index.js')).toBe( + 'debugger;\nlet value = true;\nif (value) {\n value++;\n}\n', + ); + expect(readProjectFile('src/unselected.js')).toBe( + 'debugger;let value=true;if(value) value++', + ); }); -test('does not format when lint fails in fix mode', () => { +test('formats files even when type checking fails in fix mode', () => { writeLintConfig(); - writeProjectFile('src/index.js', 'debugger;const value=true'); + writeProjectFile( + 'tsconfig.json', + '{ "compilerOptions": { "strict": true }, "include": ["src"] }', + ); + writeProjectFile('src/index.ts', 'const value: string=1'); - const result = runCheck(['--fix', 'src/index.js']); + const result = runCheck(['--fix', '--type-check', 'src/index.ts']); expect(result.status).toBe(1); - expect(`${result.stdout}\n${result.stderr}`).toContain( - "Unexpected 'debugger' statement", - ); - expect(result.stdout).not.toContain('Formatting...'); - expect(readProjectFile('src/index.js')).toBe('debugger;const value=true'); + expect(`${result.stdout}\n${result.stderr}`).toContain('TS2322'); + expect(result.stdout).toContain('Formatting completed in'); + expect(readProjectFile('src/index.ts')).toBe('const value: string = 1;\n'); }); diff --git a/website/docs/en/guide/cli/check.mdx b/website/docs/en/guide/cli/check.mdx index 4e078c5f..df1ce24e 100644 --- a/website/docs/en/guide/cli/check.mdx +++ b/website/docs/en/guide/cli/check.mdx @@ -34,7 +34,7 @@ Automatically fix linting and formatting issues: rs check --fix ``` -This first runs `rs lint --fix` to apply available lint fixes. If linting and any enabled type checking pass, it then runs `rs fmt --write` to format the updated files. +This first runs `rs lint --fix` to apply available lint fixes, then `rs fmt --write` to format the updated files. Formatting still runs if lint or type errors remain, and the command exits with a non-zero code if either step fails. ### `--type-check` diff --git a/website/docs/zh/guide/cli/check.mdx b/website/docs/zh/guide/cli/check.mdx index 28b26b06..b5701c78 100644 --- a/website/docs/zh/guide/cli/check.mdx +++ b/website/docs/zh/guide/cli/check.mdx @@ -34,7 +34,7 @@ rs check src/index.ts packages/utils rs check --fix ``` -该选项会先运行 `rs lint --fix`,自动修复 lint 问题。只有 lint 和已启用的类型检查都通过,才会继续运行 `rs fmt --write`,格式化修复后的文件。 +该选项会先运行 `rs lint --fix` 自动修复 lint 问题,再运行 `rs fmt --write` 格式化修复后的文件。即使仍有 lint 或类型错误,也会继续格式化;任一步骤失败,命令都会以非零退出码结束。 ### `--type-check` From 262e6242f6cdf75cbc375eb6d97acb7209cc4c07 Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 9 Oct 2026 21:11:52 +0800 Subject: [PATCH 2/3] test: remove overlapping check coverage --- packages/rstack/tests/cli/check.test.ts | 32 +++++++++---------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/packages/rstack/tests/cli/check.test.ts b/packages/rstack/tests/cli/check.test.ts index 44789d1a..bf368fad 100644 --- a/packages/rstack/tests/cli/check.test.ts +++ b/packages/rstack/tests/cli/check.test.ts @@ -192,22 +192,19 @@ test.each([ }, ); -test.each([false, true])( - 'preserves a formatter error exit code after lint fails (fix: %s)', - (fix) => { - writeLintConfig(); - writeProjectFile('src/index.js', 'debugger;\n'); - writeProjectFile('src/broken.json', '{ "value": }'); +test('preserves a formatter error exit code after lint fails', () => { + writeLintConfig(); + writeProjectFile('src/index.js', 'debugger;\n'); + writeProjectFile('src/broken.json', '{ "value": }'); - const result = runCheck([...(fix ? ['--fix'] : []), 'src']); + const result = runCheck(['src']); - expect(result.status).toBe(2); - expect(`${result.stdout}\n${result.stderr}`).toContain( - "Unexpected 'debugger' statement", - ); - expect(result.stderr).toContain('broken.json'); - }, -); + expect(result.status).toBe(2); + expect(`${result.stdout}\n${result.stderr}`).toContain( + "Unexpected 'debugger' statement", + ); + expect(result.stderr).toContain('broken.json'); +}); test('formats lint fixes even when unfixable errors remain', () => { writeProjectFile( @@ -220,10 +217,6 @@ define.lint([{ `, ); writeProjectFile('src/index.js', 'debugger;let value=true;if(value) value++'); - writeProjectFile( - 'src/unselected.js', - 'debugger;let value=true;if(value) value++', - ); const result = runCheck(['--fix', 'src/index.js']); @@ -235,9 +228,6 @@ define.lint([{ expect(readProjectFile('src/index.js')).toBe( 'debugger;\nlet value = true;\nif (value) {\n value++;\n}\n', ); - expect(readProjectFile('src/unselected.js')).toBe( - 'debugger;let value=true;if(value) value++', - ); }); test('formats files even when type checking fails in fix mode', () => { From 36768f7f0bf0fc3e7db5b7b1d27cef940596636a Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 9 Oct 2026 21:17:52 +0800 Subject: [PATCH 3/3] test: disable shared disk cache in doc reload fixtures --- .../tests/config/reload-doc-config/index.test.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/rstack/tests/config/reload-doc-config/index.test.ts b/packages/rstack/tests/config/reload-doc-config/index.test.ts index ac59d52e..ded4ea17 100644 --- a/packages/rstack/tests/config/reload-doc-config/index.test.ts +++ b/packages/rstack/tests/config/reload-doc-config/index.test.ts @@ -25,6 +25,8 @@ define.doc({ root: 'docs', title: '${title}', builderConfig: { + // Avoid disk cache contention between dev server processes in this fixture. + performance: { buildCache: false }, dev: { watchFiles: { paths: ${JSON.stringify(userWatchFile)}, @@ -83,6 +85,9 @@ import { title } from './test-temp-imported.ts'; define.doc({ root: 'docs', title, + builderConfig: { + performance: { buildCache: false }, + }, }); `, ); @@ -130,7 +135,12 @@ test('should restart doc dev server when an imported shared config changes', asy import { sharedConfig } from './test-temp-shared.ts'; define.extends([sharedConfig]); -define.doc({ root: 'docs' }); +define.doc({ + root: 'docs', + builderConfig: { + performance: { buildCache: false }, + }, +}); `, );