1- import { resolveCommonLanguageId , type FileRegistry } from '@volar/language-core' ;
1+ import type { FileRegistry } from '@volar/language-core' ;
22import type * as ts from 'typescript' ;
33import { createResolveModuleName } from '../resolveModuleName' ;
44
55export function decorateLanguageServiceHost (
6- virtualFiles : FileRegistry ,
6+ files : FileRegistry ,
77 languageServiceHost : ts . LanguageServiceHost ,
88 ts : typeof import ( 'typescript' ) ,
99) {
1010
1111 let extraProjectVersion = 0 ;
1212
13- const { languagePlugins } = virtualFiles ;
13+ const { languagePlugins } = files ;
1414 const exts = languagePlugins
1515 . map ( plugin => plugin . typescript ?. extraFileExtensions . map ( ext => '.' + ext . extension ) ?? [ ] )
1616 . flat ( ) ;
1717 const scripts = new Map < string , {
18- version : string ;
18+ projectVersion : string | undefined ;
19+ version : number ;
1920 snapshot : ts . IScriptSnapshot | undefined ;
2021 kind : ts . ScriptKind ;
2122 extension : string ;
@@ -26,6 +27,7 @@ export function decorateLanguageServiceHost(
2627 const resolveModuleNames = languageServiceHost . resolveModuleNames ?. bind ( languageServiceHost ) ;
2728 const getProjectVersion = languageServiceHost . getProjectVersion ?. bind ( languageServiceHost ) ;
2829 const getScriptSnapshot = languageServiceHost . getScriptSnapshot . bind ( languageServiceHost ) ;
30+ const getScriptVersion = languageServiceHost . getScriptVersion . bind ( languageServiceHost ) ;
2931 const getScriptKind = languageServiceHost . getScriptKind ?. bind ( languageServiceHost ) ;
3032
3133 // path completion
@@ -44,7 +46,7 @@ export function decorateLanguageServiceHost(
4446
4547 if ( languagePlugins . some ( language => language . typescript ?. extraFileExtensions . length ) ) {
4648
47- const resolveModuleName = createResolveModuleName ( ts , languageServiceHost , languagePlugins , fileName => virtualFiles . get ( fileName ) ) ;
49+ const resolveModuleName = createResolveModuleName ( ts , languageServiceHost , languagePlugins , fileName => files . get ( fileName ) ) ;
4850
4951 if ( resolveModuleNameLiterals ) {
5052 languageServiceHost . resolveModuleNameLiterals = (
@@ -94,6 +96,13 @@ export function decorateLanguageServiceHost(
9496 }
9597 return getScriptSnapshot ( fileName ) ;
9698 } ;
99+ languageServiceHost . getScriptVersion = fileName => {
100+ if ( exts . some ( ext => fileName . endsWith ( ext ) ) ) {
101+ updateScript ( fileName ) ;
102+ return scripts . get ( fileName ) ?. version . toString ( ) ?? '' ;
103+ }
104+ return getScriptVersion ( fileName ) ;
105+ } ;
97106
98107 if ( getScriptKind ) {
99108 languageServiceHost . getScriptKind = fileName => {
@@ -111,45 +120,59 @@ export function decorateLanguageServiceHost(
111120
112121 function updateScript ( fileName : string ) {
113122
114- const version = languageServiceHost . getScriptVersion ( fileName ) ;
123+ const version = getProjectVersion ?.( ) ;
124+ const cache = scripts . get ( fileName ) ;
115125
116- if ( version !== scripts . get ( fileName ) ?. version ) {
126+ if ( version === undefined || version !== cache ?. projectVersion ) {
117127
118- let extension = '.ts' ;
119- let snapshotSnapshot : ts . IScriptSnapshot | undefined ;
120- let scriptKind = ts . ScriptKind . TS ;
128+ const file = files . get ( fileName ) ;
129+ const script = file ?. generated ?. languagePlugin . typescript ?. getScript ( file . generated . code ) ;
121130
122- const snapshot = getScriptSnapshot ( fileName ) ;
131+ if ( script ?. code . snapshot !== cache ?. snapshot ) {
132+
133+ let extension = '.ts' ;
134+ let snapshotSnapshot : ts . IScriptSnapshot | undefined ;
135+ let scriptKind = ts . ScriptKind . TS ;
123136
124- if ( snapshot ) {
125137 extraProjectVersion ++ ;
126- const sourceFile = virtualFiles . set ( fileName , resolveCommonLanguageId ( fileName ) , snapshot ) ;
127- if ( sourceFile . generated ) {
128- const text = snapshot . getText ( 0 , snapshot . getLength ( ) ) ;
129- let patchedText = text . split ( '\n' ) . map ( line => ' ' . repeat ( line . length ) ) . join ( '\n' ) ;
130- const script = sourceFile . generated . languagePlugin . typescript ?. getScript ( sourceFile . generated . code ) ;
131- if ( script ) {
138+
139+ if ( script ) {
140+ if ( file ?. generated ) {
141+ const text = file . snapshot . getText ( 0 , file . snapshot . getLength ( ) ) ;
142+ let patchedText = text . split ( '\n' ) . map ( line => ' ' . repeat ( line . length ) ) . join ( '\n' ) ;
132143 extension = script . extension ;
133144 scriptKind = script . scriptKind ;
134145 patchedText += script . code . snapshot . getText ( 0 , script . code . snapshot . getLength ( ) ) ;
146+ snapshotSnapshot = ts . ScriptSnapshot . fromString ( patchedText ) ;
147+ if ( file . generated . languagePlugin . typescript ?. getExtraScripts ) {
148+ console . warn ( 'getExtraScripts() is not available in this use case.' ) ;
149+ }
135150 }
136- snapshotSnapshot = ts . ScriptSnapshot . fromString ( patchedText ) ;
137- if ( sourceFile . generated . languagePlugin . typescript ?. getExtraScripts ) {
138- console . warn ( 'getExtraScripts() is not available in this use case.' ) ;
139- }
151+ }
152+ else if ( files . get ( fileName ) ) {
153+ files . delete ( fileName ) ;
154+ }
155+
156+ if ( ! cache ) {
157+ scripts . set ( fileName , {
158+ projectVersion : version ,
159+ version : 0 ,
160+ extension,
161+ snapshot : snapshotSnapshot ,
162+ kind : scriptKind ,
163+ } ) ;
164+ }
165+ else {
166+ cache . projectVersion = version ;
167+ cache . version ++ ;
168+ cache . extension = extension ;
169+ cache . snapshot = snapshotSnapshot ;
170+ cache . kind = scriptKind ;
140171 }
141172 }
142- else if ( virtualFiles . get ( fileName ) ) {
143- extraProjectVersion ++ ;
144- virtualFiles . delete ( fileName ) ;
173+ else if ( cache ) {
174+ cache . projectVersion = version ;
145175 }
146-
147- scripts . set ( fileName , {
148- version,
149- extension,
150- snapshot : snapshotSnapshot ,
151- kind : scriptKind ,
152- } ) ;
153176 }
154177
155178 return scripts . get ( fileName ) ;
0 commit comments