@@ -279,73 +279,103 @@ export class SvelteSnapshotManager {
279279 }
280280
281281 private patchProjectServiceReadFile ( ) {
282- const readFile = this . projectService . host . readFile ;
283- this . projectService . host . readFile = ( path : string , encoding ?: string | undefined ) => {
284- if ( ! this . configManager . getConfig ( ) . enable ) {
285- return readFile ( path , encoding ) ;
286- }
282+ // @ts -ignore The projectService is shared across some instances, make sure we patch readFile only once
283+ if ( ! this . projectService . host [ onReadSvelteFile ] ) {
284+ this . logger . log ( 'patching projectService host readFile' ) ;
285+
286+ // @ts -ignore
287+ this . projectService . host [ onReadSvelteFile ] = [ ] ;
287288
288- // The following (very hacky) first two checks make sure that the ambient module definitions
289- // that tell TS "every import ending with .svelte is a valid module" are removed.
290- // They exist in svelte2tsx and svelte to make sure that people don't
291- // get errors in their TS files when importing Svelte files and not using our TS plugin.
292- // If someone wants to get back the behavior they can add an ambient module definition
293- // on their own.
294- const normalizedPath = path . replace ( / \\ / g, '/' ) ;
295- if ( normalizedPath . endsWith ( 'node_modules/svelte/types/runtime/ambient.d.ts' ) ) {
296- return '' ;
297- } else if ( normalizedPath . endsWith ( 'svelte2tsx/svelte-shims.d.ts' ) ) {
298- let originalText = readFile ( path ) || '' ;
299- if ( ! originalText . includes ( '// -- start svelte-ls-remove --' ) ) {
300- return originalText ; // uses an older version of svelte2tsx
289+ const readFile = this . projectService . host . readFile ;
290+ this . projectService . host . readFile = ( path : string , encoding ?: string | undefined ) => {
291+ if ( ! this . configManager . getConfig ( ) . enable ) {
292+ return readFile ( path , encoding ) ;
301293 }
302- originalText =
303- originalText . substring (
304- 0 ,
305- originalText . indexOf ( '// -- start svelte-ls-remove --' )
306- ) +
307- originalText . substring ( originalText . indexOf ( '// -- end svelte-ls-remove --' ) ) ;
308- return originalText ;
309- } else if ( isSvelteFilePath ( path ) ) {
310- this . logger . debug ( 'Read Svelte file:' , path ) ;
311- const svelteCode = readFile ( path ) || '' ;
312- try {
313- const isTsFile = true ; // TODO check file contents? TS might be okay with importing ts into js.
314- const result = svelte2tsx ( svelteCode , {
315- filename : path . split ( '/' ) . pop ( ) ,
316- isTsFile,
317- mode : 'ts' , // useNewTransformation
318- typingsNamespace : this . svelteOptions . namespace
319- } ) ;
320- const canonicalFilePath = this . projectService . toCanonicalFileName ( path ) ;
321- const existingSnapshot = this . snapshots . get ( canonicalFilePath ) ;
322- if ( existingSnapshot ) {
323- existingSnapshot . update ( svelteCode , new SourceMapper ( result . map . mappings ) ) ;
324- } else {
325- this . snapshots . set (
326- canonicalFilePath ,
327- new SvelteSnapshot (
328- this . typescript ,
329- path ,
330- svelteCode ,
331- new SourceMapper ( result . map . mappings ) ,
332- this . logger ,
333- isTsFile
334- )
294+
295+ // The following (very hacky) first two checks make sure that the ambient module definitions
296+ // that tell TS "every import ending with .svelte is a valid module" are removed.
297+ // They exist in svelte2tsx and svelte to make sure that people don't
298+ // get errors in their TS files when importing Svelte files and not using our TS plugin.
299+ // If someone wants to get back the behavior they can add an ambient module definition
300+ // on their own.
301+ const normalizedPath = path . replace ( / \\ / g, '/' ) ;
302+ if ( normalizedPath . endsWith ( 'node_modules/svelte/types/runtime/ambient.d.ts' ) ) {
303+ return '' ;
304+ } else if ( normalizedPath . endsWith ( 'svelte2tsx/svelte-shims.d.ts' ) ) {
305+ let originalText = readFile ( path ) || '' ;
306+ if ( ! originalText . includes ( '// -- start svelte-ls-remove --' ) ) {
307+ return originalText ; // uses an older version of svelte2tsx or is already patched
308+ }
309+ originalText =
310+ originalText . substring (
311+ 0 ,
312+ originalText . indexOf ( '// -- start svelte-ls-remove --' )
313+ ) +
314+ originalText . substring (
315+ originalText . indexOf ( '// -- end svelte-ls-remove --' )
335316 ) ;
317+ return originalText ;
318+ } else if ( isSvelteFilePath ( path ) ) {
319+ this . logger . debug ( 'Read Svelte file:' , path ) ;
320+ const svelteCode = readFile ( path ) || '' ;
321+ const isTsFile = true ; // TODO check file contents? TS might be okay with importing ts into js.
322+ let code : string ;
323+ let mapper : SourceMapper ;
324+
325+ try {
326+ const result = svelte2tsx ( svelteCode , {
327+ filename : path . split ( '/' ) . pop ( ) ,
328+ isTsFile,
329+ mode : 'ts' , // useNewTransformation
330+ typingsNamespace : this . svelteOptions . namespace
331+ } ) ;
332+ code = result . code ;
333+ mapper = new SourceMapper ( result . map . mappings ) ;
334+ this . logger . log ( 'Successfully read Svelte file contents of' , path ) ;
335+ } catch ( e ) {
336+ this . logger . log ( 'Error loading Svelte file:' , path , ' Using fallback.' ) ;
337+ this . logger . debug ( 'Error:' , e ) ;
338+ // Return something either way, else "X is not a module" errors will appear
339+ // in the TS files that use this file.
340+ code = 'export default class extends Svelte2TsxComponent<any,any,any> {}' ;
341+ mapper = new SourceMapper ( '' ) ;
336342 }
337- this . logger . log ( 'Successfully read Svelte file contents of' , path ) ;
338- return result . code ;
339- } catch ( e ) {
340- this . logger . log ( 'Error loading Svelte file:' , path , ' Using fallback.' ) ;
341- this . logger . debug ( 'Error:' , e ) ;
342- // Return something either way, else "X is not a module" errors will appear
343- // in the TS files that use this file.
344- return 'export default class extends Svelte2TsxComponent<any,any,any> {}' ;
343+
344+ // @ts -ignore
345+ this . projectService . host [ onReadSvelteFile ] . forEach ( ( listener ) =>
346+ listener ( path , code , isTsFile , mapper )
347+ ) ;
348+
349+ return code ;
350+ } else {
351+ return readFile ( path , encoding ) ;
352+ }
353+ } ;
354+ }
355+
356+ // @ts -ignore
357+ this . projectService . host [ onReadSvelteFile ] . push (
358+ ( path : string , svelteCode : string , isTsFile : boolean , mapper : SourceMapper ) => {
359+ const canonicalFilePath = this . projectService . toCanonicalFileName ( path ) ;
360+ const existingSnapshot = this . snapshots . get ( canonicalFilePath ) ;
361+ if ( existingSnapshot ) {
362+ existingSnapshot . update ( svelteCode , mapper ) ;
363+ } else {
364+ this . snapshots . set (
365+ canonicalFilePath ,
366+ new SvelteSnapshot (
367+ this . typescript ,
368+ path ,
369+ svelteCode ,
370+ mapper ,
371+ this . logger ,
372+ isTsFile
373+ )
374+ ) ;
345375 }
346- } else {
347- return readFile ( path , encoding ) ;
348376 }
349- } ;
377+ ) ;
350378 }
351379}
380+
381+ const onReadSvelteFile = Symbol ( 'sveltePluginPatchSymbol' ) ;
0 commit comments