From 573b5d144c441d54c2a757a3330865cfdd027109 Mon Sep 17 00:00:00 2001 From: KazariEX Date: Sat, 22 Nov 2025 23:43:34 +0800 Subject: [PATCH 1/3] fix: avoid `vue-tsc` crash during single file checks --- packages/language-core/lib/compilerOptions.ts | 141 ++++++++---------- 1 file changed, 59 insertions(+), 82 deletions(-) diff --git a/packages/language-core/lib/compilerOptions.ts b/packages/language-core/lib/compilerOptions.ts index 7ae177aedb..5ac64749d2 100644 --- a/packages/language-core/lib/compilerOptions.ts +++ b/packages/language-core/lib/compilerOptions.ts @@ -5,104 +5,81 @@ import { generateGlobalTypes, getGlobalTypesFileName } from './codegen/globalTyp import type { RawVueCompilerOptions, VueCompilerOptions, VueLanguagePlugin } from './types'; import { hyphenateTag } from './utils/shared'; -interface ParseConfigHost extends Omit {} - export interface ParsedCommandLine extends Omit { vueOptions: VueCompilerOptions; } -export function createParsedCommandLineByJson( - ts: typeof import('typescript'), - host: ParseConfigHost, - rootDir: string, - json: any, - configFileName?: string, -): ParsedCommandLine { - const extendedPaths = new Set(); - const proxyHost = { - ...host, - readFile(fileName: string) { - if (!fileName.endsWith('/package.json')) { - extendedPaths.add(fileName); - } - return host.readFile(fileName); - }, - readDirectory() { - return []; - }, - }; - const parsed = ts.parseJsonConfigFileContent(json, proxyHost, rootDir, {}, configFileName); - const resolver = new CompilerOptionsResolver(host.fileExists); - - for (const extendPath of [...extendedPaths].reverse()) { - try { - const configFile = ts.readJsonConfigFile(extendPath, host.readFile); - const obj = ts.convertToObject(configFile, []); - const rawOptions: RawVueCompilerOptions = obj?.vueCompilerOptions ?? {}; - resolver.addConfig(rawOptions, path.dirname(configFile.fileName)); - } - catch {} - } - - // ensure the rootDir is added to the config roots - resolver.addConfig({}, rootDir); - - return { - ...parsed, - vueOptions: resolver.build(), - }; -} +export const createParsedCommandLineByJson = createCommandLineParser( + (ts, host, rootDir: string, json: any, configFileName?: string) => { + // `parseJsonConfigFileContent` is missing in tsc + return 'parseJsonConfigFileContent' in (ts as any) + ? ts.parseJsonConfigFileContent(json, host, rootDir, {}, configFileName) + : ts.parseJsonSourceFileConfigFileContent( + ts.parseJsonText(configFileName ?? 'tsconfig.json', JSON.stringify(json)), + host, + rootDir, + {}, + configFileName, + ); + }, +); -export function createParsedCommandLine( - ts: typeof import('typescript'), - host: ParseConfigHost, - configFileName: string, -): ParsedCommandLine { - try { - const extendedPaths = new Set(); - const proxyHost = { - ...host, - readFile(fileName: string) { - if (!fileName.endsWith('/package.json')) { - extendedPaths.add(fileName); - } - return host.readFile(fileName); - }, - readDirectory() { - return []; - }, - }; - const config = ts.readJsonConfigFile(configFileName, proxyHost.readFile); - const parsed = ts.parseJsonSourceFileConfigFileContent( +export const createParsedCommandLine = createCommandLineParser( + (ts, host, configFileName: string) => { + const config = ts.readJsonConfigFile(configFileName, host.readFile); + return ts.parseJsonSourceFileConfigFileContent( config, - proxyHost, + host, path.dirname(configFileName), {}, configFileName, ); - const resolver = new CompilerOptionsResolver(host.fileExists); + }, +); - for (const extendPath of [...extendedPaths].reverse()) { - try { - const configFile = ts.readJsonConfigFile(extendPath, host.readFile); - const obj = ts.convertToObject(configFile, []); - const rawOptions: RawVueCompilerOptions = obj?.vueCompilerOptions ?? {}; - resolver.addConfig(rawOptions, path.dirname(configFile.fileName)); +function createCommandLineParser( + getter: (ts: typeof import('typescript'), host: ts.ParseConfigHost, ...args: T) => ts.ParsedCommandLine, +) { + return (ts: typeof import('typescript'), host: ts.ParseConfigHost, ...args: T): ParsedCommandLine => { + try { + const extendedPaths = new Set(); + const proxyHost = { + ...host, + readFile(fileName: string) { + if (!fileName.endsWith('/package.json')) { + extendedPaths.add(fileName); + } + return host.readFile(fileName); + }, + readDirectory() { + return []; + }, + }; + const parsed = getter(ts, proxyHost, ...args); + + const resolver = new CompilerOptionsResolver(host.fileExists); + for (const extendPath of [...extendedPaths].reverse()) { + try { + const configFile = ts.readJsonConfigFile(extendPath, host.readFile); + const obj = ts.convertToObject(configFile, []); + const rawOptions: RawVueCompilerOptions = obj?.vueCompilerOptions ?? {}; + resolver.addConfig(rawOptions, path.dirname(configFile.fileName)); + } + catch {} } - catch {} + + return { + ...parsed, + vueOptions: resolver.build(), + }; } + catch {} return { - ...parsed, - vueOptions: resolver.build(), + options: {}, + errors: [], + vueOptions: getDefaultCompilerOptions(), }; - } - catch {} - - return { - options: {}, - errors: [], - vueOptions: getDefaultCompilerOptions(), }; } From 97393646a17754fc0cb16951626372507fff567a Mon Sep 17 00:00:00 2001 From: KazariEX Date: Sat, 22 Nov 2025 23:47:09 +0800 Subject: [PATCH 2/3] fix: types --- packages/language-core/lib/compilerOptions.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/language-core/lib/compilerOptions.ts b/packages/language-core/lib/compilerOptions.ts index 5ac64749d2..b889c2bd44 100644 --- a/packages/language-core/lib/compilerOptions.ts +++ b/packages/language-core/lib/compilerOptions.ts @@ -38,9 +38,17 @@ export const createParsedCommandLine = createCommandLineParser( ); function createCommandLineParser( - getter: (ts: typeof import('typescript'), host: ts.ParseConfigHost, ...args: T) => ts.ParsedCommandLine, + getParsedCommandLine: ( + ts: typeof import('typescript'), + host: ts.ParseConfigHost, + ...args: T + ) => ts.ParsedCommandLine, ) { - return (ts: typeof import('typescript'), host: ts.ParseConfigHost, ...args: T): ParsedCommandLine => { + return ( + ts: typeof import('typescript'), + host: Omit, + ...args: T + ): ParsedCommandLine => { try { const extendedPaths = new Set(); const proxyHost = { @@ -55,7 +63,7 @@ function createCommandLineParser( return []; }, }; - const parsed = getter(ts, proxyHost, ...args); + const parsed = getParsedCommandLine(ts, proxyHost, ...args); const resolver = new CompilerOptionsResolver(host.fileExists); for (const extendPath of [...extendedPaths].reverse()) { From 451c18a25cfba1b0108ef70480097498e00dd886 Mon Sep 17 00:00:00 2001 From: KazariEX Date: Sat, 22 Nov 2025 23:51:02 +0800 Subject: [PATCH 3/3] refactor: rename --- packages/language-core/lib/compilerOptions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/language-core/lib/compilerOptions.ts b/packages/language-core/lib/compilerOptions.ts index b889c2bd44..622b3b196b 100644 --- a/packages/language-core/lib/compilerOptions.ts +++ b/packages/language-core/lib/compilerOptions.ts @@ -9,7 +9,7 @@ export interface ParsedCommandLine extends Omit { // `parseJsonConfigFileContent` is missing in tsc return 'parseJsonConfigFileContent' in (ts as any) @@ -24,7 +24,7 @@ export const createParsedCommandLineByJson = createCommandLineParser( }, ); -export const createParsedCommandLine = createCommandLineParser( +export const createParsedCommandLine = create( (ts, host, configFileName: string) => { const config = ts.readJsonConfigFile(configFileName, host.readFile); return ts.parseJsonSourceFileConfigFileContent( @@ -37,7 +37,7 @@ export const createParsedCommandLine = createCommandLineParser( }, ); -function createCommandLineParser( +function create( getParsedCommandLine: ( ts: typeof import('typescript'), host: ts.ParseConfigHost,