@@ -269,7 +269,7 @@ export class SvelteSnapshot {
269269}
270270
271271export class SvelteSnapshotManager {
272- private snapshots = new Map < string , SvelteSnapshot > ( ) ;
272+ private snapshots : Map < string , SvelteSnapshot > ;
273273
274274 constructor (
275275 private typescript : typeof ts ,
@@ -280,7 +280,9 @@ export class SvelteSnapshotManager {
280280 /** undefined if no node_modules with Svelte next to tsconfig.json */
281281 private svelteCompiler : typeof import ( 'svelte/compiler' ) | undefined
282282 ) {
283- this . patchProjectServiceReadFile ( ) ;
283+ this . patchProjectService ( ) ;
284+ // @ts -expect-error
285+ this . snapshots = this . projectService [ snapshots ] ;
284286 }
285287
286288 get ( fileName : string ) {
@@ -321,92 +323,78 @@ export class SvelteSnapshotManager {
321323 return snapshot ;
322324 }
323325
324- private patchProjectServiceReadFile ( ) {
325- // @ts -ignore The projectService is shared across some instances, make sure we patch readFile only once
326- if ( ! this . projectService . host [ onReadSvelteFile ] ) {
327- this . logger . log ( 'patching projectService host readFile' ) ;
326+ private patchProjectService ( ) {
327+ // @ts -expect-error The projectService is shared across some instances, make sure we patch only once
328+ if ( this . projectService [ snapshots ] ) return ;
328329
329- // @ts -ignore
330- this . projectService . host [ onReadSvelteFile ] = [ ] ;
330+ this . logger . log ( 'patching projectService' ) ;
331331
332- const readFile = this . projectService . host . readFile ;
333- this . projectService . host . readFile = ( path : string , encoding ?: string | undefined ) => {
334- if ( ! this . configManager . getConfig ( ) . enable ) {
335- return readFile ( path , encoding ) ;
336- }
332+ // @ts -expect-error Snapshots are stored on the projectService, so they are shared across all instances
333+ this . snapshots = this . projectService [ snapshots ] = new Map ( ) ;
337334
338- // The following (very hacky) first two checks make sure that the ambient module definitions
339- // that tell TS "every import ending with .svelte is a valid module" are removed.
340- // They exist in svelte2tsx and svelte to make sure that people don't
341- // get errors in their TS files when importing Svelte files and not using our TS plugin.
342- // If someone wants to get back the behavior they can add an ambient module definition
343- // on their own.
344- const normalizedPath = path . replace ( / \\ / g, '/' ) ;
345- if ( normalizedPath . endsWith ( 'node_modules/svelte/types/runtime/ambient.d.ts' ) ) {
346- return '' ;
347- } else if ( normalizedPath . endsWith ( 'svelte2tsx/svelte-jsx.d.ts' ) ) {
348- // Remove the dom lib reference to not load these ambient types in case
349- // the user has a tsconfig.json with different lib settings like in
350- // https://github.com/sveltejs/language-tools/issues/1733
351- const originalText = readFile ( path ) || '' ;
352- const toReplace = '/// <reference lib="dom" />' ;
353- return originalText . replace ( toReplace , ' ' . repeat ( toReplace . length ) ) ;
354- } else if ( normalizedPath . endsWith ( 'svelte2tsx/svelte-shims.d.ts' ) ) {
355- let originalText = readFile ( path ) || '' ;
356- if ( ! originalText . includes ( '// -- start svelte-ls-remove --' ) ) {
357- return originalText ; // uses an older version of svelte2tsx or is already patched
358- }
359- const startIdx = originalText . indexOf ( '// -- start svelte-ls-remove --' ) ;
360- const endIdx = originalText . indexOf ( '// -- end svelte-ls-remove --' ) ;
361- originalText =
362- originalText . substring ( 0 , startIdx ) +
363- ' ' . repeat ( endIdx - startIdx ) +
364- originalText . substring ( endIdx ) ;
365- return originalText ;
366- } else if ( isSvelteFilePath ( path ) ) {
367- this . logger . debug ( 'Read Svelte file:' , path ) ;
368- const svelteCode = readFile ( path ) || '' ;
369- const isTsFile = true ; // TODO check file contents? TS might be okay with importing ts into js.
370- let code : string ;
371- let mapper : SourceMapper ;
372-
373- try {
374- const result = svelte2tsx ( svelteCode , {
375- filename : path . split ( '/' ) . pop ( ) ,
376- isTsFile,
377- mode : 'ts' ,
378- typingsNamespace : this . svelteOptions . namespace ,
379- // Don't search for compiler from current path - could be a different one from which we have loaded the svelte2tsx globals
380- parse : this . svelteCompiler ?. parse ,
381- version : this . svelteCompiler ?. VERSION
382- } ) ;
383- code = result . code ;
384- mapper = new SourceMapper ( result . map . mappings ) ;
385- this . logger . log ( 'Successfully read Svelte file contents of' , path ) ;
386- } catch ( e ) {
387- this . logger . log ( 'Error loading Svelte file:' , path , ' Using fallback.' ) ;
388- this . logger . debug ( 'Error:' , e ) ;
389- // Return something either way, else "X is not a module" errors will appear
390- // in the TS files that use this file.
391- code = 'export default class extends Svelte2TsxComponent<any,any,any> {}' ;
392- mapper = new SourceMapper ( '' ) ;
393- }
394-
395- // @ts -ignore
396- this . projectService . host [ onReadSvelteFile ] . forEach ( ( listener ) =>
397- listener ( path , svelteCode , isTsFile , mapper )
398- ) ;
335+ const readFile = this . projectService . host . readFile ;
336+ this . projectService . host . readFile = ( path : string , encoding ?: string | undefined ) => {
337+ if ( ! this . configManager . getConfig ( ) . enable ) {
338+ return readFile ( path , encoding ) ;
339+ }
399340
400- return code ;
401- } else {
402- return readFile ( path , encoding ) ;
341+ // The following (very hacky) first two checks make sure that the ambient module definitions
342+ // that tell TS "every import ending with .svelte is a valid module" are removed.
343+ // They exist in svelte2tsx and svelte to make sure that people don't
344+ // get errors in their TS files when importing Svelte files and not using our TS plugin.
345+ // If someone wants to get back the behavior they can add an ambient module definition
346+ // on their own.
347+ const normalizedPath = path . replace ( / \\ / g, '/' ) ;
348+ if ( normalizedPath . endsWith ( 'node_modules/svelte/types/runtime/ambient.d.ts' ) ) {
349+ return '' ;
350+ } else if ( normalizedPath . endsWith ( 'svelte2tsx/svelte-jsx.d.ts' ) ) {
351+ // Remove the dom lib reference to not load these ambient types in case
352+ // the user has a tsconfig.json with different lib settings like in
353+ // https://github.com/sveltejs/language-tools/issues/1733
354+ const originalText = readFile ( path ) || '' ;
355+ const toReplace = '/// <reference lib="dom" />' ;
356+ return originalText . replace ( toReplace , ' ' . repeat ( toReplace . length ) ) ;
357+ } else if ( normalizedPath . endsWith ( 'svelte2tsx/svelte-shims.d.ts' ) ) {
358+ let originalText = readFile ( path ) || '' ;
359+ if ( ! originalText . includes ( '// -- start svelte-ls-remove --' ) ) {
360+ return originalText ; // uses an older version of svelte2tsx or is already patched
361+ }
362+ const startIdx = originalText . indexOf ( '// -- start svelte-ls-remove --' ) ;
363+ const endIdx = originalText . indexOf ( '// -- end svelte-ls-remove --' ) ;
364+ originalText =
365+ originalText . substring ( 0 , startIdx ) +
366+ ' ' . repeat ( endIdx - startIdx ) +
367+ originalText . substring ( endIdx ) ;
368+ return originalText ;
369+ } else if ( isSvelteFilePath ( path ) ) {
370+ this . logger . debug ( 'Read Svelte file:' , path ) ;
371+ const svelteCode = readFile ( path ) || '' ;
372+ const isTsFile = true ; // TODO check file contents? TS might be okay with importing ts into js.
373+ let code : string ;
374+ let mapper : SourceMapper ;
375+
376+ try {
377+ const result = svelte2tsx ( svelteCode , {
378+ filename : path . split ( '/' ) . pop ( ) ,
379+ isTsFile,
380+ mode : 'ts' ,
381+ typingsNamespace : this . svelteOptions . namespace ,
382+ // Don't search for compiler from current path - could be a different one from which we have loaded the svelte2tsx globals
383+ parse : this . svelteCompiler ?. parse ,
384+ version : this . svelteCompiler ?. VERSION
385+ } ) ;
386+ code = result . code ;
387+ mapper = new SourceMapper ( result . map . mappings ) ;
388+ this . logger . log ( 'Successfully read Svelte file contents of' , path ) ;
389+ } catch ( e ) {
390+ this . logger . log ( 'Error loading Svelte file:' , path , ' Using fallback.' ) ;
391+ this . logger . debug ( 'Error:' , e ) ;
392+ // Return something either way, else "X is not a module" errors will appear
393+ // in the TS files that use this file.
394+ code = 'export default class extends Svelte2TsxComponent<any,any,any> {}' ;
395+ mapper = new SourceMapper ( '' ) ;
403396 }
404- } ;
405- }
406397
407- // @ts -ignore
408- this . projectService . host [ onReadSvelteFile ] . push (
409- ( path : string , svelteCode : string , isTsFile : boolean , mapper : SourceMapper ) => {
410398 const canonicalFilePath = this . projectService . toCanonicalFileName ( path ) ;
411399 const existingSnapshot = this . snapshots . get ( canonicalFilePath ) ;
412400 if ( existingSnapshot ) {
@@ -424,9 +412,13 @@ export class SvelteSnapshotManager {
424412 )
425413 ) ;
426414 }
415+
416+ return code ;
417+ } else {
418+ return readFile ( path , encoding ) ;
427419 }
428- ) ;
420+ } ;
429421 }
430422}
431423
432- const onReadSvelteFile = Symbol ( 'sveltePluginPatchSymbol' ) ;
424+ const snapshots = Symbol ( 'sveltePluginPatchSymbol' ) ;
0 commit comments