Skip to content

Commit 11a448c

Browse files
authored
fix(language-core): avoid vue-tsc crash during single file checks (#5768)
1 parent 2dda0aa commit 11a448c

File tree

1 file changed

+67
-82
lines changed

1 file changed

+67
-82
lines changed

packages/language-core/lib/compilerOptions.ts

Lines changed: 67 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -5,104 +5,89 @@ import { generateGlobalTypes, getGlobalTypesFileName } from './codegen/globalTyp
55
import type { RawVueCompilerOptions, VueCompilerOptions, VueLanguagePlugin } from './types';
66
import { hyphenateTag } from './utils/shared';
77

8-
interface ParseConfigHost extends Omit<ts.ParseConfigHost, 'readDirectory'> {}
9-
108
export interface ParsedCommandLine extends Omit<ts.ParsedCommandLine, 'fileNames'> {
119
vueOptions: VueCompilerOptions;
1210
}
1311

14-
export function createParsedCommandLineByJson(
15-
ts: typeof import('typescript'),
16-
host: ParseConfigHost,
17-
rootDir: string,
18-
json: any,
19-
configFileName?: string,
20-
): ParsedCommandLine {
21-
const extendedPaths = new Set<string>();
22-
const proxyHost = {
23-
...host,
24-
readFile(fileName: string) {
25-
if (!fileName.endsWith('/package.json')) {
26-
extendedPaths.add(fileName);
27-
}
28-
return host.readFile(fileName);
29-
},
30-
readDirectory() {
31-
return [];
32-
},
33-
};
34-
const parsed = ts.parseJsonConfigFileContent(json, proxyHost, rootDir, {}, configFileName);
35-
const resolver = new CompilerOptionsResolver(host.fileExists);
36-
37-
for (const extendPath of [...extendedPaths].reverse()) {
38-
try {
39-
const configFile = ts.readJsonConfigFile(extendPath, host.readFile);
40-
const obj = ts.convertToObject(configFile, []);
41-
const rawOptions: RawVueCompilerOptions = obj?.vueCompilerOptions ?? {};
42-
resolver.addConfig(rawOptions, path.dirname(configFile.fileName));
43-
}
44-
catch {}
45-
}
46-
47-
// ensure the rootDir is added to the config roots
48-
resolver.addConfig({}, rootDir);
49-
50-
return {
51-
...parsed,
52-
vueOptions: resolver.build(),
53-
};
54-
}
12+
export const createParsedCommandLineByJson = create(
13+
(ts, host, rootDir: string, json: any, configFileName?: string) => {
14+
// `parseJsonConfigFileContent` is missing in tsc
15+
return 'parseJsonConfigFileContent' in (ts as any)
16+
? ts.parseJsonConfigFileContent(json, host, rootDir, {}, configFileName)
17+
: ts.parseJsonSourceFileConfigFileContent(
18+
ts.parseJsonText(configFileName ?? 'tsconfig.json', JSON.stringify(json)),
19+
host,
20+
rootDir,
21+
{},
22+
configFileName,
23+
);
24+
},
25+
);
5526

56-
export function createParsedCommandLine(
57-
ts: typeof import('typescript'),
58-
host: ParseConfigHost,
59-
configFileName: string,
60-
): ParsedCommandLine {
61-
try {
62-
const extendedPaths = new Set<string>();
63-
const proxyHost = {
64-
...host,
65-
readFile(fileName: string) {
66-
if (!fileName.endsWith('/package.json')) {
67-
extendedPaths.add(fileName);
68-
}
69-
return host.readFile(fileName);
70-
},
71-
readDirectory() {
72-
return [];
73-
},
74-
};
75-
const config = ts.readJsonConfigFile(configFileName, proxyHost.readFile);
76-
const parsed = ts.parseJsonSourceFileConfigFileContent(
27+
export const createParsedCommandLine = create(
28+
(ts, host, configFileName: string) => {
29+
const config = ts.readJsonConfigFile(configFileName, host.readFile);
30+
return ts.parseJsonSourceFileConfigFileContent(
7731
config,
78-
proxyHost,
32+
host,
7933
path.dirname(configFileName),
8034
{},
8135
configFileName,
8236
);
83-
const resolver = new CompilerOptionsResolver(host.fileExists);
37+
},
38+
);
8439

85-
for (const extendPath of [...extendedPaths].reverse()) {
86-
try {
87-
const configFile = ts.readJsonConfigFile(extendPath, host.readFile);
88-
const obj = ts.convertToObject(configFile, []);
89-
const rawOptions: RawVueCompilerOptions = obj?.vueCompilerOptions ?? {};
90-
resolver.addConfig(rawOptions, path.dirname(configFile.fileName));
40+
function create<T extends any[]>(
41+
getParsedCommandLine: (
42+
ts: typeof import('typescript'),
43+
host: ts.ParseConfigHost,
44+
...args: T
45+
) => ts.ParsedCommandLine,
46+
) {
47+
return (
48+
ts: typeof import('typescript'),
49+
host: Omit<ts.ParseConfigHost, 'readDirectory'>,
50+
...args: T
51+
): ParsedCommandLine => {
52+
try {
53+
const extendedPaths = new Set<string>();
54+
const proxyHost = {
55+
...host,
56+
readFile(fileName: string) {
57+
if (!fileName.endsWith('/package.json')) {
58+
extendedPaths.add(fileName);
59+
}
60+
return host.readFile(fileName);
61+
},
62+
readDirectory() {
63+
return [];
64+
},
65+
};
66+
const parsed = getParsedCommandLine(ts, proxyHost, ...args);
67+
68+
const resolver = new CompilerOptionsResolver(host.fileExists);
69+
for (const extendPath of [...extendedPaths].reverse()) {
70+
try {
71+
const configFile = ts.readJsonConfigFile(extendPath, host.readFile);
72+
const obj = ts.convertToObject(configFile, []);
73+
const rawOptions: RawVueCompilerOptions = obj?.vueCompilerOptions ?? {};
74+
resolver.addConfig(rawOptions, path.dirname(configFile.fileName));
75+
}
76+
catch {}
9177
}
92-
catch {}
78+
79+
return {
80+
...parsed,
81+
vueOptions: resolver.build(),
82+
};
9383
}
84+
catch {}
9485

9586
return {
96-
...parsed,
97-
vueOptions: resolver.build(),
87+
options: {},
88+
errors: [],
89+
vueOptions: getDefaultCompilerOptions(),
9890
};
99-
}
100-
catch {}
101-
102-
return {
103-
options: {},
104-
errors: [],
105-
vueOptions: getDefaultCompilerOptions(),
10691
};
10792
}
10893

0 commit comments

Comments
 (0)