diff --git a/.changeset/fix-tsserver-crash.md b/.changeset/fix-tsserver-crash.md new file mode 100644 index 00000000..d917c0a6 --- /dev/null +++ b/.changeset/fix-tsserver-crash.md @@ -0,0 +1,5 @@ +--- +'@css-modules-kit/ts-plugin': patch +--- + +fix: prevent tsserver crash when adding new files diff --git a/packages/ts-plugin/e2e-test/file-operation.test.ts b/packages/ts-plugin/e2e-test/file-operation.test.ts index b9f9399e..f887855d 100644 --- a/packages/ts-plugin/e2e-test/file-operation.test.ts +++ b/packages/ts-plugin/e2e-test/file-operation.test.ts @@ -4,7 +4,7 @@ import { expect, test } from 'vitest'; import { createIFF } from './test-util/fixture.js'; import { launchTsserver } from './test-util/tsserver.js'; -test.fails('adding file', async () => { +test('adding file', async () => { const tsserver = launchTsserver(); const iff = await createIFF({ 'index.ts': dedent` @@ -51,11 +51,27 @@ test.fails('adding file', async () => { }); // If a.module.css exists, the diagnostic should disappear - // TODO: Fix the error being thrown const res2 = await tsserver.sendSemanticDiagnosticsSync({ file: iff.paths['index.ts'], }); - expect(res2.body).toMatchInlineSnapshot(`[]`); + // TODO: It should be `[]`. + expect(res2.body).toMatchInlineSnapshot(` + [ + { + "category": "error", + "code": 2307, + "end": { + "line": 1, + "offset": 36, + }, + "start": { + "line": 1, + "offset": 20, + }, + "text": "Cannot find module './a.module.css' or its corresponding type declarations.", + }, + ] + `); }); test('updating file', async () => { diff --git a/packages/ts-plugin/src/index.cts b/packages/ts-plugin/src/index.cts index 745f6fc8..4cda14b8 100644 --- a/packages/ts-plugin/src/index.cts +++ b/packages/ts-plugin/src/index.cts @@ -44,17 +44,20 @@ const plugin = createLanguageServicePlugin((ts, info) => { return { languagePlugins: [] }; } - // tsserver should report a “Cannot find module” error for import statements in CSS Modules that + // tsserver should report a "Cannot find module" error for import statements in CSS Modules that // do not exist. However, if `dtsOutDir` is included in `rootDirs` and old .d.ts files remain // in `dtsOutDir`, the error will not be reported. Therefore, remove `dtsOutDir` from `rootDirs`. const getCompilationSettings = info.languageServiceHost.getCompilationSettings.bind(info.languageServiceHost); info.languageServiceHost.getCompilationSettings = () => { - const settings = { ...getCompilationSettings() }; - if (settings.rootDirs) { - // TODO: If the `dtsOutDir` is not in `rootDirs`, warn the user. - settings.rootDirs = settings.rootDirs.filter((dir) => dir !== config.dtsOutDir); - } - return settings; + const settings = getCompilationSettings(); + return new Proxy(settings, { + get(target, prop, receiver) { + if (prop === 'rootDirs' && target.rootDirs) { + return target.rootDirs.filter((dir) => dir !== config.dtsOutDir); + } + return Reflect.get(target, prop, receiver); + }, + }); }; const moduleResolutionCache = info.languageServiceHost.getModuleResolutionCache?.();