Skip to content

Commit e3f8b91

Browse files
authored
fix(language-core): prevent append globalTypes to virtual file (#4806)
1 parent 5c7e153 commit e3f8b91

File tree

8 files changed

+60
-99
lines changed

8 files changed

+60
-99
lines changed

packages/component-meta/lib/base.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function createCheckerByJsonConfigBase(
2929
rootDir = rootDir.replace(windowsPathReg, '/');
3030
return baseCreate(
3131
ts,
32-
() => vue.createParsedCommandLineByJson(ts, ts.sys, rootDir, json),
32+
() => vue.createParsedCommandLineByJson(ts, ts.sys, rootDir, json, undefined, true),
3333
checkerOptions,
3434
rootDir,
3535
path.join(rootDir, 'jsconfig.json.global.vue')
@@ -44,7 +44,7 @@ export function createCheckerBase(
4444
tsconfig = tsconfig.replace(windowsPathReg, '/');
4545
return baseCreate(
4646
ts,
47-
() => vue.createParsedCommandLine(ts, ts.sys, tsconfig),
47+
() => vue.createParsedCommandLine(ts, ts.sys, tsconfig, true),
4848
checkerOptions,
4949
path.dirname(tsconfig),
5050
tsconfig + '.global.vue'
@@ -86,10 +86,7 @@ export function baseCreate(
8686
const vueLanguagePlugin = vue.createVueLanguagePlugin<string>(
8787
ts,
8888
projectHost.getCompilationSettings(),
89-
{
90-
...commandLine.vueOptions,
91-
__setupedGlobalTypes: () => true,
92-
},
89+
commandLine.vueOptions,
9390
id => id
9491
);
9592
const language = vue.createLanguage(

packages/language-core/lib/codegen/script/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export interface ScriptCodegenOptions {
5454
export function* generateScript(options: ScriptCodegenOptions): Generator<Code, ScriptCodegenContext> {
5555
const ctx = createScriptCodegenContext(options);
5656

57-
if (options.vueCompilerOptions.__setupedGlobalTypes?.()) {
57+
if (options.vueCompilerOptions.__setupedGlobalTypes) {
5858
yield `/// <reference types=".vue-global-types/${options.vueCompilerOptions.lib}_${options.vueCompilerOptions.target}_${options.vueCompilerOptions.strictTemplates}.d.ts" />${newLine}`;
5959
}
6060
else {
@@ -151,7 +151,7 @@ export function* generateScript(options: ScriptCodegenOptions): Generator<Code,
151151
yield `type __VLS_IntrinsicElementsCompletion = __VLS_IntrinsicElements${endOfLine}`;
152152
}
153153
yield* ctx.localTypes.generate([...ctx.localTypes.getUsedNames()]);
154-
if (!options.vueCompilerOptions.__setupedGlobalTypes?.()) {
154+
if (!options.vueCompilerOptions.__setupedGlobalTypes) {
155155
yield generateGlobalTypes('local', options.vueCompilerOptions.lib, options.vueCompilerOptions.target, options.vueCompilerOptions.strictTemplates);
156156
}
157157

packages/language-core/lib/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export interface VueCompilerOptions {
5555
experimentalModelPropName: Record<string, Record<string, boolean | Record<string, string> | Record<string, string>[]>>;
5656

5757
// internal
58-
__setupedGlobalTypes?: () => boolean;
58+
__setupedGlobalTypes?: boolean;
5959
__test?: boolean;
6060
}
6161

packages/language-core/lib/utils/ts.ts

+45-3
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@ import type * as ts from 'typescript';
33
import * as path from 'path-browserify';
44
import type { RawVueCompilerOptions, VueCompilerOptions, VueLanguagePlugin } from '../types';
55
import { getAllExtensions } from '../languagePlugin';
6+
import { generateGlobalTypes } from '../codegen/globalTypes';
67

78
export type ParsedCommandLine = ts.ParsedCommandLine & {
89
vueOptions: VueCompilerOptions;
910
};
1011

1112
export function createParsedCommandLineByJson(
1213
ts: typeof import('typescript'),
13-
parseConfigHost: ts.ParseConfigHost,
14+
parseConfigHost: ts.ParseConfigHost & {
15+
writeFile?(path: string, data: string): void;
16+
},
1417
rootDir: string,
1518
json: any,
16-
configFileName = rootDir + '/jsconfig.json'
19+
configFileName = rootDir + '/jsconfig.json',
20+
skipGlobalTypesSetup = false
1721
): ParsedCommandLine {
1822

1923
const proxyHost = proxyParseConfigHostForExtendConfigPaths(parseConfigHost);
@@ -31,6 +35,12 @@ export function createParsedCommandLineByJson(
3135
}
3236

3337
const resolvedVueOptions = resolveVueCompilerOptions(vueOptions);
38+
if (skipGlobalTypesSetup) {
39+
resolvedVueOptions.__setupedGlobalTypes = true;
40+
}
41+
else {
42+
resolvedVueOptions.__setupedGlobalTypes = setupGlobalTypes(rootDir, resolvedVueOptions, parseConfigHost);
43+
}
3444
const parsed = ts.parseJsonConfigFileContent(
3545
json,
3646
proxyHost.host,
@@ -60,7 +70,8 @@ export function createParsedCommandLineByJson(
6070
export function createParsedCommandLine(
6171
ts: typeof import('typescript'),
6272
parseConfigHost: ts.ParseConfigHost,
63-
tsConfigPath: string
73+
tsConfigPath: string,
74+
skipGlobalTypesSetup = false
6475
): ParsedCommandLine {
6576
try {
6677
const proxyHost = proxyParseConfigHostForExtendConfigPaths(parseConfigHost);
@@ -79,6 +90,12 @@ export function createParsedCommandLine(
7990
}
8091

8192
const resolvedVueOptions = resolveVueCompilerOptions(vueOptions);
93+
if (skipGlobalTypesSetup) {
94+
resolvedVueOptions.__setupedGlobalTypes = true;
95+
}
96+
else {
97+
resolvedVueOptions.__setupedGlobalTypes = setupGlobalTypes(path.dirname(tsConfigPath), resolvedVueOptions, parseConfigHost);
98+
}
8299
const parsed = ts.parseJsonSourceFileConfigFileContent(
83100
config,
84101
proxyHost.host,
@@ -260,3 +277,28 @@ export function resolveVueCompilerOptions(vueOptions: Partial<VueCompilerOptions
260277
).map(([k, v]) => [camelize(k), v])),
261278
};
262279
}
280+
281+
export function setupGlobalTypes(rootDir: string, vueOptions: VueCompilerOptions, host: {
282+
fileExists(path: string): boolean;
283+
writeFile?(path: string, data: string): void;
284+
}) {
285+
if (!host.writeFile) {
286+
return false;
287+
}
288+
try {
289+
let dir = rootDir;
290+
while (!host.fileExists(path.resolve(dir, `node_modules/${vueOptions.lib}/package.json`))) {
291+
const parentDir = path.resolve(dir, '..');
292+
if (dir === parentDir) {
293+
throw 0;
294+
}
295+
dir = parentDir;
296+
}
297+
const globalTypesPath = path.resolve(dir, `node_modules/.vue-global-types/${vueOptions.lib}_${vueOptions.target}_${vueOptions.strictTemplates}.d.ts`);
298+
const globalTypesContents = generateGlobalTypes('global', vueOptions.lib, vueOptions.target, vueOptions.strictTemplates);
299+
host.writeFile(globalTypesPath, globalTypesContents);
300+
return true;
301+
} catch {
302+
return false;
303+
}
304+
}

packages/language-server/lib/initialize.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ export function initialize(
2222
let compilerOptions: ts.CompilerOptions;
2323
let vueCompilerOptions: VueCompilerOptions;
2424
if (configFileName) {
25-
let commandLine = createParsedCommandLine(ts, sys, configFileName);
25+
let commandLine = createParsedCommandLine(ts, sys, configFileName, true);
2626
let sysVersion = sys.version;
2727
let newSysVersion = await sys.sync();
2828
while (sysVersion !== newSysVersion) {
29-
commandLine = createParsedCommandLine(ts, sys, configFileName);
29+
commandLine = createParsedCommandLine(ts, sys, configFileName, true);
3030
sysVersion = newSysVersion;
3131
newSysVersion = await sys.sync();
3232
}
@@ -44,10 +44,7 @@ export function initialize(
4444
createVueLanguagePlugin(
4545
ts,
4646
compilerOptions,
47-
{
48-
...vueCompilerOptions,
49-
__setupedGlobalTypes: () => true,
50-
},
47+
vueCompilerOptions,
5148
s => uriConverter.asFileName(s)
5249
),
5350
],

packages/tsc/index.ts

+1-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { runTsc } from '@volar/typescript/lib/quickstart/runTsc';
2-
import * as path from 'path';
32
import * as vue from '@vue/language-core';
43

54
const windowsPathReg = /\\/g;
@@ -22,31 +21,10 @@ export function run(tscPath = require.resolve('typescript/lib/tsc')) {
2221
runExtensions.length === allExtensions.length
2322
&& runExtensions.every(ext => allExtensions.includes(ext))
2423
) {
25-
let setupedGlobalTypes = false;
26-
try {
27-
let dir = typeof configFilePath === 'string'
28-
? configFilePath
29-
: options.host?.getCurrentDirectory() ?? ts.sys.getCurrentDirectory();
30-
while (!ts.sys.directoryExists(path.resolve(dir, 'node_modules'))) {
31-
const parentDir = path.resolve(dir, '..');
32-
if (dir === parentDir) {
33-
throw 0;
34-
}
35-
dir = parentDir;
36-
}
37-
const globalTypesPath = path.resolve(dir, `node_modules/.vue-global-types/${vueOptions.lib}_${vueOptions.target}_${vueOptions.strictTemplates}.d.ts`);
38-
const globalTypesContents = vue.generateGlobalTypes('global', vueOptions.lib, vueOptions.target, vueOptions.strictTemplates);
39-
ts.sys.writeFile(globalTypesPath, globalTypesContents);
40-
setupedGlobalTypes = true;
41-
} catch { }
42-
4324
const vueLanguagePlugin = vue.createVueLanguagePlugin<string>(
4425
ts,
4526
options.options,
46-
{
47-
...vueOptions,
48-
__setupedGlobalTypes: () => setupedGlobalTypes,
49-
},
27+
vueOptions,
5028
id => id
5129
);
5230
return { languagePlugins: [vueLanguagePlugin] };

packages/tsc/tests/dts.spec.ts

+3-23
Original file line numberDiff line numberDiff line change
@@ -25,38 +25,18 @@ describe('vue-tsc-dts', () => {
2525
};
2626

2727
let vueOptions: vue.VueCompilerOptions;
28+
2829
const createProgram = proxyCreateProgram(ts, ts.createProgram, (ts, options) => {
2930
const { configFilePath } = options.options;
31+
3032
vueOptions = typeof configFilePath === 'string'
3133
? vue.createParsedCommandLine(ts, ts.sys, configFilePath.replace(windowsPathReg, '/')).vueOptions
3234
: vue.resolveVueCompilerOptions({ extensions: ['.vue', '.cext'] });
3335

34-
let setupedGlobalTypes = false;
35-
36-
try {
37-
let dir = typeof configFilePath === 'string'
38-
? configFilePath
39-
: options.host?.getCurrentDirectory() ?? ts.sys.getCurrentDirectory();
40-
while (!ts.sys.directoryExists(path.resolve(dir, 'node_modules'))) {
41-
const parentDir = path.resolve(dir, '..');
42-
if (dir === parentDir) {
43-
throw 0;
44-
}
45-
dir = parentDir;
46-
}
47-
const globalTypesPath = path.resolve(dir, `node_modules/.vue-global-types/${vueOptions.lib}_${vueOptions.target}_${vueOptions.strictTemplates}.d.ts`);
48-
const globalTypesContents = vue.generateGlobalTypes('global', vueOptions.lib, vueOptions.target, vueOptions.strictTemplates);
49-
ts.sys.writeFile(globalTypesPath, globalTypesContents);
50-
setupedGlobalTypes = true;
51-
} catch { }
52-
5336
const vueLanguagePlugin = vue.createVueLanguagePlugin<string>(
5437
ts,
5538
options.options,
56-
{
57-
...vueOptions,
58-
__setupedGlobalTypes: () => setupedGlobalTypes,
59-
},
39+
vueOptions,
6040
id => id
6141
);
6242
return [vueLanguagePlugin];

packages/typescript-plugin/index.ts

+2-35
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
import { createLanguageServicePlugin } from '@volar/typescript/lib/quickstart/createLanguageServicePlugin';
2-
import * as path from 'path';
32
import * as vue from '@vue/language-core';
43
import { proxyLanguageServiceForVue } from './lib/common';
54
import { startNamedPipeServer } from './lib/server';
65
import type * as ts from 'typescript';
76

87
const windowsPathReg = /\\/g;
98
const vueCompilerOptions = new WeakMap<ts.server.Project, vue.VueCompilerOptions>();
10-
const setupedProjects = new WeakSet<ts.server.Project>();
11-
12-
const basePlugin = createLanguageServicePlugin(
9+
const plugin = createLanguageServicePlugin(
1310
(ts, info) => {
1411
const vueOptions = getVueCompilerOptions();
1512
const languagePlugin = vue.createVueLanguagePlugin<string>(
1613
ts,
1714
info.languageServiceHost.getCompilationSettings(),
18-
{
19-
...vueOptions,
20-
__setupedGlobalTypes: () => setupedProjects.has(info.project),
21-
},
15+
vueOptions,
2216
id => id
2317
);
2418

@@ -56,32 +50,5 @@ const basePlugin = createLanguageServicePlugin(
5650
}
5751
}
5852
);
59-
const plugin: ts.server.PluginModuleFactory = mods => {
60-
const pluginModule = basePlugin(mods);
61-
62-
return {
63-
...pluginModule,
64-
getExternalFiles(proj, updateLevel = 0) {
65-
const options = vueCompilerOptions.get(proj);
66-
if (updateLevel >= 1 && options) {
67-
try {
68-
let dir = proj.getCurrentDirectory();
69-
while (!proj.directoryExists(path.resolve(dir, 'node_modules'))) {
70-
const parentDir = path.resolve(dir, '..');
71-
if (dir === parentDir) {
72-
throw 0;
73-
}
74-
dir = parentDir;
75-
}
76-
const globalTypesPath = path.resolve(dir, `node_modules/.vue-global-types/${options.lib}_${options.target}_${options.strictTemplates}.d.ts`);
77-
const globalTypesContents = vue.generateGlobalTypes('global', options.lib, options.target, options.strictTemplates);
78-
proj.writeFile(globalTypesPath, globalTypesContents);
79-
setupedProjects.add(proj);
80-
} catch { }
81-
}
82-
return pluginModule.getExternalFiles?.(proj, updateLevel) ?? [];
83-
},
84-
};
85-
};
8653

8754
export = plugin;

0 commit comments

Comments
 (0)