Skip to content

Commit d4c0c5e

Browse files
committed
switch holder when original host file when deleted
1 parent 81dcb5e commit d4c0c5e

File tree

5 files changed

+96
-56
lines changed

5 files changed

+96
-56
lines changed

packages/language-core/src/generators/script.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function* generate(
3434
} | undefined,
3535
compilerOptions: ts.CompilerOptions,
3636
vueCompilerOptions: VueCompilerOptions,
37-
globalTypesHolder: string,
37+
globalTypesHolder: string | undefined,
3838
getGeneratedLength: () => number,
3939
linkedCodeMappings: Mapping[] = [],
4040
codegenStack: boolean,

packages/language-core/src/languageModule.ts

+59-24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { LanguagePlugin } from '@volar/language-core';
22
import * as path from 'path-browserify';
3-
import { getDefaultVueLanguagePlugins } from './plugins';
3+
import { getDefaultVueLanguagePlugins, createPluginContext } from './plugins';
44
import { VueFile } from './virtualFile/vueFile';
55
import { VueCompilerOptions, VueLanguagePlugin } from './types';
66
import type * as ts from 'typescript/lib/tsserverlibrary';
@@ -32,6 +32,25 @@ function getVueFileRegistry(key: string, plugins: VueLanguagePlugin[]) {
3232
return fileRegistry;
3333
}
3434

35+
function getFileRegistryKey(
36+
compilerOptions: ts.CompilerOptions,
37+
vueCompilerOptions: VueCompilerOptions,
38+
plugins: ReturnType<VueLanguagePlugin>[],
39+
globalTypesHolder: string | undefined,
40+
) {
41+
const values = [
42+
globalTypesHolder,
43+
...Object.keys(vueCompilerOptions)
44+
.sort()
45+
.filter(key => key !== 'plugins')
46+
.map(key => [key, vueCompilerOptions[key as keyof VueCompilerOptions]]),
47+
[...new Set(plugins.map(plugin => plugin.requiredCompilerOptions ?? []).flat())]
48+
.sort()
49+
.map(key => [key, compilerOptions[key as keyof ts.CompilerOptions]]),
50+
];
51+
return JSON.stringify(values);
52+
}
53+
3554
export function createVueLanguage(
3655
ts: typeof import('typescript/lib/tsserverlibrary'),
3756
compilerOptions: ts.CompilerOptions = {},
@@ -42,6 +61,14 @@ export function createVueLanguage(
4261

4362
const vueCompilerOptions = resolveVueCompilerOptions(_vueCompilerOptions);
4463
const allowLanguageIds = new Set(['vue']);
64+
const pluginContext = createPluginContext(
65+
ts,
66+
compilerOptions,
67+
vueCompilerOptions,
68+
codegenStack,
69+
globalTypesHolder,
70+
);
71+
const plugins = getDefaultVueLanguagePlugins(pluginContext);
4572

4673
if (vueCompilerOptions.extensions.includes('.md')) {
4774
allowLanguageIds.add('markdown');
@@ -51,38 +78,19 @@ export function createVueLanguage(
5178
}
5279

5380
let fileRegistry: Map<string, VueFile> | undefined;
54-
let plugins: ReturnType<VueLanguagePlugin>[] = [];
5581

5682
return {
5783
createVirtualFile(fileName, languageId, snapshot) {
5884
if (allowLanguageIds.has(languageId)) {
5985

6086
if (!fileRegistry) {
6187

62-
globalTypesHolder ??= fileName;
63-
64-
const keys = [
65-
globalTypesHolder,
66-
...Object.keys(vueCompilerOptions)
67-
.sort()
68-
.filter(key => key !== 'plugins')
69-
.map(key => [key, vueCompilerOptions[key as keyof VueCompilerOptions]]),
70-
[...new Set(plugins.map(plugin => plugin.requiredCompilerOptions ?? []).flat())]
71-
.sort()
72-
.map(key => [key, compilerOptions[key as keyof ts.CompilerOptions]]),
73-
];
88+
pluginContext.globalTypesHolder ??= fileName;
7489

7590
fileRegistry = getVueFileRegistry(
76-
JSON.stringify(keys),
91+
getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins, pluginContext.globalTypesHolder),
7792
vueCompilerOptions.plugins,
7893
);
79-
plugins = getDefaultVueLanguagePlugins(
80-
ts,
81-
compilerOptions,
82-
vueCompilerOptions,
83-
codegenStack,
84-
globalTypesHolder,
85-
);
8694
}
8795

8896
if (fileRegistry.has(fileName)) {
@@ -95,8 +103,35 @@ export function createVueLanguage(
95103
return vueFile;
96104
}
97105
},
98-
updateVirtualFile(sourceFile, snapshot) {
99-
sourceFile.update(snapshot);
106+
updateVirtualFile(vueFile, snapshot) {
107+
vueFile.update(snapshot);
108+
},
109+
disposeVirtualFile(vueFile, files) {
110+
fileRegistry?.delete(vueFile.fileName);
111+
if (vueFile.fileName === pluginContext.globalTypesHolder) {
112+
if (fileRegistry?.size) {
113+
for (const [fileName, file] of fileRegistry!) {
114+
pluginContext.globalTypesHolder = fileName;
115+
116+
fileRegistry = getVueFileRegistry(
117+
getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins, pluginContext.globalTypesHolder),
118+
vueCompilerOptions.plugins,
119+
);
120+
121+
files.updateSourceFile(
122+
file.fileName,
123+
file.languageId,
124+
// force dirty
125+
{ ...file.snapshot },
126+
);
127+
break;
128+
}
129+
}
130+
else {
131+
fileRegistry = undefined;
132+
pluginContext.globalTypesHolder = undefined;
133+
}
134+
}
100135
},
101136
typescript: {
102137
resolveSourceFileName(tsFileName) {

packages/language-core/src/plugins.ts

+21-16
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,13 @@ import { VueCompilerOptions, VueLanguagePlugin } from './types';
1212
import * as CompilerDOM from '@vue/compiler-dom';
1313
import * as CompilerVue2 from './utils/vue2TemplateCompiler';
1414

15-
export function getDefaultVueLanguagePlugins(
15+
export function createPluginContext(
1616
ts: typeof import('typescript/lib/tsserverlibrary'),
1717
compilerOptions: ts.CompilerOptions,
1818
vueCompilerOptions: VueCompilerOptions,
1919
codegenStack: boolean,
20-
globalTypesHolder: string,
20+
globalTypesHolder: string | undefined,
2121
) {
22-
23-
const plugins: VueLanguagePlugin[] = [
24-
useMdFilePlugin, // .md for VitePress
25-
useHtmlFilePlugin, // .html for PetiteVue
26-
useVueFilePlugin, // .vue and others for Vue
27-
useHtmlTemplatePlugin,
28-
useVueSfcStyles,
29-
useVueSfcCustomBlocks,
30-
useVueSfcScriptsFormat,
31-
useVueSfcTemplate,
32-
useVueTsx,
33-
...vueCompilerOptions.plugins,
34-
];
3522
const pluginCtx: Parameters<VueLanguagePlugin>[0] = {
3623
modules: {
3724
'@vue/compiler-dom': vueCompilerOptions.target < 3
@@ -47,8 +34,26 @@ export function getDefaultVueLanguagePlugins(
4734
codegenStack,
4835
globalTypesHolder,
4936
};
37+
return pluginCtx;
38+
}
39+
40+
export function getDefaultVueLanguagePlugins(pluginContext: Parameters<VueLanguagePlugin>[0]) {
41+
42+
const plugins: VueLanguagePlugin[] = [
43+
useMdFilePlugin, // .md for VitePress
44+
useHtmlFilePlugin, // .html for PetiteVue
45+
useVueFilePlugin, // .vue and others for Vue
46+
useHtmlTemplatePlugin,
47+
useVueSfcStyles,
48+
useVueSfcCustomBlocks,
49+
useVueSfcScriptsFormat,
50+
useVueSfcTemplate,
51+
useVueTsx,
52+
...pluginContext.vueCompilerOptions.plugins,
53+
];
54+
;
5055
const pluginInstances = plugins
51-
.map(plugin => plugin(pluginCtx))
56+
.map(plugin => plugin(pluginContext))
5257
.sort((a, b) => {
5358
const aOrder = a.order ?? 0;
5459
const bOrder = b.order ?? 0;

packages/language-core/src/plugins/vue-tsx.ts

+14-14
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ export default plugin;
123123
function createTsx(
124124
fileName: string,
125125
_sfc: Sfc,
126-
{ vueCompilerOptions, compilerOptions, codegenStack, modules, globalTypesHolder }: Parameters<VueLanguagePlugin>[0],
126+
ctx: Parameters<VueLanguagePlugin>[0],
127127
) {
128128

129-
const ts = modules.typescript;
129+
const ts = ctx.modules.typescript;
130130
const lang = computed(() => {
131131
return !_sfc.script && !_sfc.scriptSetup ? 'ts'
132132
: _sfc.scriptSetup && _sfc.scriptSetup.lang !== 'js' ? _sfc.scriptSetup.lang
@@ -140,11 +140,11 @@ function createTsx(
140140
);
141141
const scriptSetupRanges = computed(() =>
142142
_sfc.scriptSetup
143-
? parseScriptSetupRanges(ts, _sfc.scriptSetup.ast, vueCompilerOptions)
143+
? parseScriptSetupRanges(ts, _sfc.scriptSetup.ast, ctx.vueCompilerOptions)
144144
: undefined
145145
);
146146
const shouldGenerateScopedClasses = computed(() => {
147-
const option = vueCompilerOptions.experimentalResolveStyleCssClasses;
147+
const option = ctx.vueCompilerOptions.experimentalResolveStyleCssClasses;
148148
return _sfc.styles.some(s => {
149149
return option === 'always' || (option === 'scoped' && s.scoped);
150150
});
@@ -158,7 +158,7 @@ function createTsx(
158158
}
159159

160160
for (const style of _sfc.styles) {
161-
const option = vueCompilerOptions.experimentalResolveStyleCssClasses;
161+
const option = ctx.vueCompilerOptions.experimentalResolveStyleCssClasses;
162162
if (option === 'always' || (option === 'scoped' && style.scoped)) {
163163
for (const className of style.classNames) {
164164
classes.add(className.text.substring(1));
@@ -181,15 +181,15 @@ function createTsx(
181181
const inlineCssCodegenStacks: string[] = [];
182182
const codegen = generateTemplate(
183183
ts,
184-
compilerOptions,
185-
vueCompilerOptions,
184+
ctx.compilerOptions,
185+
ctx.vueCompilerOptions,
186186
_sfc.template,
187187
shouldGenerateScopedClasses(),
188188
stylesScopedClasses(),
189189
hasScriptSetupSlots(),
190190
slotsAssignName(),
191191
propsAssignName(),
192-
codegenStack,
192+
ctx.codegenStack,
193193
);
194194

195195
let current = codegen.next();
@@ -205,7 +205,7 @@ function createTsx(
205205
else if (type === 'inlineCss') {
206206
inlineCssCodes.push(code);
207207
}
208-
if (codegenStack) {
208+
if (ctx.codegenStack) {
209209
if (type === 'ts') {
210210
tsCodegenStacks.push(stack);
211211
}
@@ -254,15 +254,15 @@ function createTsx(
254254
hasSlot: _template.hasSlot,
255255
tagNames: new Set(_template.tagOffsetsMap.keys()),
256256
} : undefined,
257-
compilerOptions,
258-
vueCompilerOptions,
259-
globalTypesHolder,
257+
ctx.compilerOptions,
258+
ctx.vueCompilerOptions,
259+
ctx.globalTypesHolder,
260260
() => generatedLength,
261261
linkedCodeMappings,
262-
codegenStack,
262+
ctx.codegenStack,
263263
)) {
264264
codes.push(code);
265-
if (codegenStack) {
265+
if (ctx.codegenStack) {
266266
codeStacks.push({ stack, length: 1 });
267267
}
268268
generatedLength += typeof code === 'string'

packages/language-core/src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export type VueLanguagePlugin = (ctx: {
6666
compilerOptions: ts.CompilerOptions;
6767
vueCompilerOptions: VueCompilerOptions;
6868
codegenStack: boolean;
69-
globalTypesHolder: string;
69+
globalTypesHolder: string | undefined;
7070
}) => {
7171
version: 1;
7272
name?: string;

0 commit comments

Comments
 (0)