Skip to content

Commit

Permalink
switch holder when original host file when deleted
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Dec 14, 2023
1 parent 81dcb5e commit d4c0c5e
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 56 deletions.
2 changes: 1 addition & 1 deletion packages/language-core/src/generators/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function* generate(
} | undefined,
compilerOptions: ts.CompilerOptions,
vueCompilerOptions: VueCompilerOptions,
globalTypesHolder: string,
globalTypesHolder: string | undefined,
getGeneratedLength: () => number,
linkedCodeMappings: Mapping[] = [],
codegenStack: boolean,
Expand Down
83 changes: 59 additions & 24 deletions packages/language-core/src/languageModule.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { LanguagePlugin } from '@volar/language-core';
import * as path from 'path-browserify';
import { getDefaultVueLanguagePlugins } from './plugins';
import { getDefaultVueLanguagePlugins, createPluginContext } from './plugins';
import { VueFile } from './virtualFile/vueFile';
import { VueCompilerOptions, VueLanguagePlugin } from './types';
import type * as ts from 'typescript/lib/tsserverlibrary';
Expand Down Expand Up @@ -32,6 +32,25 @@ function getVueFileRegistry(key: string, plugins: VueLanguagePlugin[]) {
return fileRegistry;
}

function getFileRegistryKey(
compilerOptions: ts.CompilerOptions,
vueCompilerOptions: VueCompilerOptions,
plugins: ReturnType<VueLanguagePlugin>[],
globalTypesHolder: string | undefined,
) {
const values = [
globalTypesHolder,
...Object.keys(vueCompilerOptions)
.sort()
.filter(key => key !== 'plugins')
.map(key => [key, vueCompilerOptions[key as keyof VueCompilerOptions]]),
[...new Set(plugins.map(plugin => plugin.requiredCompilerOptions ?? []).flat())]
.sort()
.map(key => [key, compilerOptions[key as keyof ts.CompilerOptions]]),
];
return JSON.stringify(values);
}

export function createVueLanguage(
ts: typeof import('typescript/lib/tsserverlibrary'),
compilerOptions: ts.CompilerOptions = {},
Expand All @@ -42,6 +61,14 @@ export function createVueLanguage(

const vueCompilerOptions = resolveVueCompilerOptions(_vueCompilerOptions);
const allowLanguageIds = new Set(['vue']);
const pluginContext = createPluginContext(
ts,
compilerOptions,
vueCompilerOptions,
codegenStack,
globalTypesHolder,
);
const plugins = getDefaultVueLanguagePlugins(pluginContext);

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

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

return {
createVirtualFile(fileName, languageId, snapshot) {
if (allowLanguageIds.has(languageId)) {

if (!fileRegistry) {

globalTypesHolder ??= fileName;

const keys = [
globalTypesHolder,
...Object.keys(vueCompilerOptions)
.sort()
.filter(key => key !== 'plugins')
.map(key => [key, vueCompilerOptions[key as keyof VueCompilerOptions]]),
[...new Set(plugins.map(plugin => plugin.requiredCompilerOptions ?? []).flat())]
.sort()
.map(key => [key, compilerOptions[key as keyof ts.CompilerOptions]]),
];
pluginContext.globalTypesHolder ??= fileName;

fileRegistry = getVueFileRegistry(
JSON.stringify(keys),
getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins, pluginContext.globalTypesHolder),
vueCompilerOptions.plugins,
);
plugins = getDefaultVueLanguagePlugins(
ts,
compilerOptions,
vueCompilerOptions,
codegenStack,
globalTypesHolder,
);
}

if (fileRegistry.has(fileName)) {
Expand All @@ -95,8 +103,35 @@ export function createVueLanguage(
return vueFile;
}
},
updateVirtualFile(sourceFile, snapshot) {
sourceFile.update(snapshot);
updateVirtualFile(vueFile, snapshot) {
vueFile.update(snapshot);
},
disposeVirtualFile(vueFile, files) {

Check failure on line 109 in packages/language-core/src/languageModule.ts

View workflow job for this annotation

GitHub Actions / build (16, macos-latest)

Type '(vueFile: any, files: any) => void' is not assignable to type '(virtualFile: VueFile) => void'.

Check failure on line 109 in packages/language-core/src/languageModule.ts

View workflow job for this annotation

GitHub Actions / build (16, macos-latest)

Parameter 'vueFile' implicitly has an 'any' type.

Check failure on line 109 in packages/language-core/src/languageModule.ts

View workflow job for this annotation

GitHub Actions / build (16, macos-latest)

Parameter 'files' implicitly has an 'any' type.

Check failure on line 109 in packages/language-core/src/languageModule.ts

View workflow job for this annotation

GitHub Actions / build (16, ubuntu-latest)

Type '(vueFile: any, files: any) => void' is not assignable to type '(virtualFile: VueFile) => void'.

Check failure on line 109 in packages/language-core/src/languageModule.ts

View workflow job for this annotation

GitHub Actions / build (16, ubuntu-latest)

Parameter 'vueFile' implicitly has an 'any' type.

Check failure on line 109 in packages/language-core/src/languageModule.ts

View workflow job for this annotation

GitHub Actions / build (16, ubuntu-latest)

Parameter 'files' implicitly has an 'any' type.

Check failure on line 109 in packages/language-core/src/languageModule.ts

View workflow job for this annotation

GitHub Actions / build (16, ubuntu-latest)

Type '(vueFile: any, files: any) => void' is not assignable to type '(virtualFile: VueFile) => void'.

Check failure on line 109 in packages/language-core/src/languageModule.ts

View workflow job for this annotation

GitHub Actions / build (16, ubuntu-latest)

Parameter 'vueFile' implicitly has an 'any' type.

Check failure on line 109 in packages/language-core/src/languageModule.ts

View workflow job for this annotation

GitHub Actions / build (16, ubuntu-latest)

Parameter 'files' implicitly has an 'any' type.
fileRegistry?.delete(vueFile.fileName);
if (vueFile.fileName === pluginContext.globalTypesHolder) {
if (fileRegistry?.size) {
for (const [fileName, file] of fileRegistry!) {
pluginContext.globalTypesHolder = fileName;

fileRegistry = getVueFileRegistry(
getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins, pluginContext.globalTypesHolder),
vueCompilerOptions.plugins,
);

files.updateSourceFile(
file.fileName,
file.languageId,
// force dirty
{ ...file.snapshot },
);
break;
}
}
else {
fileRegistry = undefined;
pluginContext.globalTypesHolder = undefined;
}
}
},
typescript: {
resolveSourceFileName(tsFileName) {
Expand Down
37 changes: 21 additions & 16 deletions packages/language-core/src/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,13 @@ import { VueCompilerOptions, VueLanguagePlugin } from './types';
import * as CompilerDOM from '@vue/compiler-dom';
import * as CompilerVue2 from './utils/vue2TemplateCompiler';

export function getDefaultVueLanguagePlugins(
export function createPluginContext(
ts: typeof import('typescript/lib/tsserverlibrary'),
compilerOptions: ts.CompilerOptions,
vueCompilerOptions: VueCompilerOptions,
codegenStack: boolean,
globalTypesHolder: string,
globalTypesHolder: string | undefined,
) {

const plugins: VueLanguagePlugin[] = [
useMdFilePlugin, // .md for VitePress
useHtmlFilePlugin, // .html for PetiteVue
useVueFilePlugin, // .vue and others for Vue
useHtmlTemplatePlugin,
useVueSfcStyles,
useVueSfcCustomBlocks,
useVueSfcScriptsFormat,
useVueSfcTemplate,
useVueTsx,
...vueCompilerOptions.plugins,
];
const pluginCtx: Parameters<VueLanguagePlugin>[0] = {
modules: {
'@vue/compiler-dom': vueCompilerOptions.target < 3
Expand All @@ -47,8 +34,26 @@ export function getDefaultVueLanguagePlugins(
codegenStack,
globalTypesHolder,
};
return pluginCtx;
}

export function getDefaultVueLanguagePlugins(pluginContext: Parameters<VueLanguagePlugin>[0]) {

const plugins: VueLanguagePlugin[] = [
useMdFilePlugin, // .md for VitePress
useHtmlFilePlugin, // .html for PetiteVue
useVueFilePlugin, // .vue and others for Vue
useHtmlTemplatePlugin,
useVueSfcStyles,
useVueSfcCustomBlocks,
useVueSfcScriptsFormat,
useVueSfcTemplate,
useVueTsx,
...pluginContext.vueCompilerOptions.plugins,
];
;
const pluginInstances = plugins
.map(plugin => plugin(pluginCtx))
.map(plugin => plugin(pluginContext))
.sort((a, b) => {
const aOrder = a.order ?? 0;
const bOrder = b.order ?? 0;
Expand Down
28 changes: 14 additions & 14 deletions packages/language-core/src/plugins/vue-tsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ export default plugin;
function createTsx(
fileName: string,
_sfc: Sfc,
{ vueCompilerOptions, compilerOptions, codegenStack, modules, globalTypesHolder }: Parameters<VueLanguagePlugin>[0],
ctx: Parameters<VueLanguagePlugin>[0],
) {

const ts = modules.typescript;
const ts = ctx.modules.typescript;
const lang = computed(() => {
return !_sfc.script && !_sfc.scriptSetup ? 'ts'
: _sfc.scriptSetup && _sfc.scriptSetup.lang !== 'js' ? _sfc.scriptSetup.lang
Expand All @@ -140,11 +140,11 @@ function createTsx(
);
const scriptSetupRanges = computed(() =>
_sfc.scriptSetup
? parseScriptSetupRanges(ts, _sfc.scriptSetup.ast, vueCompilerOptions)
? parseScriptSetupRanges(ts, _sfc.scriptSetup.ast, ctx.vueCompilerOptions)
: undefined
);
const shouldGenerateScopedClasses = computed(() => {
const option = vueCompilerOptions.experimentalResolveStyleCssClasses;
const option = ctx.vueCompilerOptions.experimentalResolveStyleCssClasses;
return _sfc.styles.some(s => {
return option === 'always' || (option === 'scoped' && s.scoped);
});
Expand All @@ -158,7 +158,7 @@ function createTsx(
}

for (const style of _sfc.styles) {
const option = vueCompilerOptions.experimentalResolveStyleCssClasses;
const option = ctx.vueCompilerOptions.experimentalResolveStyleCssClasses;
if (option === 'always' || (option === 'scoped' && style.scoped)) {
for (const className of style.classNames) {
classes.add(className.text.substring(1));
Expand All @@ -181,15 +181,15 @@ function createTsx(
const inlineCssCodegenStacks: string[] = [];
const codegen = generateTemplate(
ts,
compilerOptions,
vueCompilerOptions,
ctx.compilerOptions,
ctx.vueCompilerOptions,
_sfc.template,
shouldGenerateScopedClasses(),
stylesScopedClasses(),
hasScriptSetupSlots(),
slotsAssignName(),
propsAssignName(),
codegenStack,
ctx.codegenStack,
);

let current = codegen.next();
Expand All @@ -205,7 +205,7 @@ function createTsx(
else if (type === 'inlineCss') {
inlineCssCodes.push(code);
}
if (codegenStack) {
if (ctx.codegenStack) {
if (type === 'ts') {
tsCodegenStacks.push(stack);
}
Expand Down Expand Up @@ -254,15 +254,15 @@ function createTsx(
hasSlot: _template.hasSlot,
tagNames: new Set(_template.tagOffsetsMap.keys()),
} : undefined,
compilerOptions,
vueCompilerOptions,
globalTypesHolder,
ctx.compilerOptions,
ctx.vueCompilerOptions,
ctx.globalTypesHolder,
() => generatedLength,
linkedCodeMappings,
codegenStack,
ctx.codegenStack,
)) {
codes.push(code);
if (codegenStack) {
if (ctx.codegenStack) {
codeStacks.push({ stack, length: 1 });
}
generatedLength += typeof code === 'string'
Expand Down
2 changes: 1 addition & 1 deletion packages/language-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export type VueLanguagePlugin = (ctx: {
compilerOptions: ts.CompilerOptions;
vueCompilerOptions: VueCompilerOptions;
codegenStack: boolean;
globalTypesHolder: string;
globalTypesHolder: string | undefined;
}) => {
version: 1;
name?: string;
Expand Down

0 comments on commit d4c0c5e

Please sign in to comment.