11import type { LanguagePlugin } from '@volar/language-core' ;
22import * as path from 'path-browserify' ;
3- import { getDefaultVueLanguagePlugins } from './plugins' ;
3+ import { getDefaultVueLanguagePlugins , createPluginContext } from './plugins' ;
44import { VueFile } from './virtualFile/vueFile' ;
55import { VueCompilerOptions , VueLanguagePlugin } from './types' ;
66import type * as ts from 'typescript/lib/tsserverlibrary' ;
@@ -32,32 +32,43 @@ 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+
3554export function createVueLanguage (
3655 ts : typeof import ( 'typescript/lib/tsserverlibrary' ) ,
3756 compilerOptions : ts . CompilerOptions = { } ,
3857 _vueCompilerOptions : Partial < VueCompilerOptions > = { } ,
3958 codegenStack : boolean = false ,
59+ globalTypesHolder ?: string
4060) : LanguagePlugin < VueFile > {
4161
4262 const vueCompilerOptions = resolveVueCompilerOptions ( _vueCompilerOptions ) ;
43- const plugins = getDefaultVueLanguagePlugins (
63+ const allowLanguageIds = new Set ( [ 'vue' ] ) ;
64+ const pluginContext = createPluginContext (
4465 ts ,
4566 compilerOptions ,
4667 vueCompilerOptions ,
4768 codegenStack ,
69+ globalTypesHolder ,
4870 ) ;
49- const keys = [
50- ...Object . keys ( vueCompilerOptions )
51- . sort ( )
52- . filter ( key => key !== 'plugins' )
53- . map ( key => [ key , vueCompilerOptions [ key as keyof VueCompilerOptions ] ] ) ,
54- [ ...new Set ( plugins . map ( plugin => plugin . requiredCompilerOptions ?? [ ] ) . flat ( ) ) ]
55- . sort ( )
56- . map ( key => [ key , compilerOptions [ key as keyof ts . CompilerOptions ] ] ) ,
57- ] ;
58- const fileRegistry = getVueFileRegistry ( JSON . stringify ( keys ) , _vueCompilerOptions . plugins ?? [ ] ) ;
59-
60- const allowLanguageIds = new Set ( [ 'vue' ] ) ;
71+ const plugins = getDefaultVueLanguagePlugins ( pluginContext ) ;
6172
6273 if ( vueCompilerOptions . extensions . includes ( '.md' ) ) {
6374 allowLanguageIds . add ( 'markdown' ) ;
@@ -66,21 +77,61 @@ export function createVueLanguage(
6677 allowLanguageIds . add ( 'html' ) ;
6778 }
6879
80+ let fileRegistry : Map < string , VueFile > | undefined ;
81+
6982 return {
70- createVirtualFile ( id , languageId , snapshot ) {
83+ createVirtualFile ( fileName , languageId , snapshot ) {
7184 if ( allowLanguageIds . has ( languageId ) ) {
72- if ( fileRegistry . has ( id ) ) {
73- const reusedVueFile = fileRegistry . get ( id ) ! ;
85+
86+ if ( ! fileRegistry ) {
87+
88+ pluginContext . globalTypesHolder ??= fileName ;
89+
90+ fileRegistry = getVueFileRegistry (
91+ getFileRegistryKey ( compilerOptions , vueCompilerOptions , plugins , pluginContext . globalTypesHolder ) ,
92+ vueCompilerOptions . plugins ,
93+ ) ;
94+ }
95+
96+ if ( fileRegistry . has ( fileName ) ) {
97+ const reusedVueFile = fileRegistry . get ( fileName ) ! ;
7498 reusedVueFile . update ( snapshot ) ;
7599 return reusedVueFile ;
76100 }
77- const vueFile = new VueFile ( id , languageId , snapshot , vueCompilerOptions , plugins , ts , codegenStack ) ;
78- fileRegistry . set ( id , vueFile ) ;
101+ const vueFile = new VueFile ( fileName , languageId , snapshot , vueCompilerOptions , plugins , ts , codegenStack ) ;
102+ fileRegistry . set ( fileName , vueFile ) ;
79103 return vueFile ;
80104 }
81105 } ,
82- updateVirtualFile ( sourceFile , snapshot ) {
83- 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+ }
84135 } ,
85136 typescript : {
86137 resolveSourceFileName ( tsFileName ) {
@@ -106,9 +157,10 @@ export function createLanguages(
106157 compilerOptions : ts . CompilerOptions = { } ,
107158 vueCompilerOptions : Partial < VueCompilerOptions > = { } ,
108159 codegenStack : boolean = false ,
160+ globalTypesHolder ?: string
109161) : LanguagePlugin [ ] {
110162 return [
111- createVueLanguage ( ts , compilerOptions , vueCompilerOptions , codegenStack ) ,
163+ createVueLanguage ( ts , compilerOptions , vueCompilerOptions , codegenStack , globalTypesHolder ) ,
112164 ...vueCompilerOptions . experimentalAdditionalLanguageModules ?. map ( module => require ( module ) ) ?? [ ] ,
113165 ] ;
114166}
0 commit comments