11import { SourceMap } from '@volar/source-map' ;
22import type * as ts from 'typescript/lib/tsserverlibrary' ;
33import { MirrorMap } from './mirrorMap' ;
4- import type { FileRangeCapabilities , Language , VirtualFile } from './types' ;
5-
6- export interface Source {
7- fileName : string ;
8- languageId : string ;
9- snapshot : ts . IScriptSnapshot ;
10- root ?: VirtualFile ;
11- language ?: Language ;
12- }
4+ import type { FileRangeCapabilities , Language , SourceFile , VirtualFile } from './types' ;
5+
6+ const caseSensitive = false ; // TODO: use ts.sys.useCaseSensitiveFileNames
137
148export function createFileProvider ( languages : Language [ ] , sync : ( ) => void ) {
159
16- const sourceFiles = new Map < string , Source > ( ) ;
17- const virtualFiles = new Map < string , { virtualFile : VirtualFile , source : Source ; } > ( ) ;
10+ const sourceFileRegistry = new Map < string , SourceFile > ( ) ;
11+ const virtualFileRegistry = new Map < string , { virtualFile : VirtualFile , source : SourceFile ; } > ( ) ;
1812 const virtualFileMaps = new WeakMap < ts . IScriptSnapshot , Map < string , [ ts . IScriptSnapshot , SourceMap < FileRangeCapabilities > ] > > ( ) ;
1913 const virtualFileToMirrorMap = new WeakMap < ts . IScriptSnapshot , MirrorMap | undefined > ( ) ;
14+ const normalizeId = caseSensitive
15+ ? ( id : string ) => id
16+ : ( id : string ) => id . toLowerCase ( ) ;
2017
2118 return {
22- getAllSources ( ) {
19+ getAllSourceFiles ( ) {
2320 sync ( ) ;
24- return sourceFiles ;
21+ return sourceFileRegistry . values ( ) ;
2522 } ,
26- updateSource ( fileName : string , snapshot : ts . IScriptSnapshot , languageId : string ) : VirtualFile | undefined {
27- const key = normalizePath ( fileName ) ;
28- const value = sourceFiles . get ( key ) ;
23+ updateSourceFile ( id : string , snapshot : ts . IScriptSnapshot , languageId : string ) : VirtualFile | undefined {
24+ const value = sourceFileRegistry . get ( normalizeId ( id ) ) ;
2925 if ( value ) {
3026 if ( value . languageId !== languageId ) {
3127 // languageId changed
32- this . deleteSource ( fileName ) ;
33- return this . updateSource ( fileName , snapshot , languageId ) ;
28+ this . deleteSourceFile ( id ) ;
29+ return this . updateSourceFile ( id , snapshot , languageId ) ;
3430 }
3531 else if ( value . snapshot !== snapshot ) {
3632 value . snapshot = snapshot ;
@@ -46,24 +42,23 @@ export function createFileProvider(languages: Language[], sync: () => void) {
4642 }
4743 }
4844 for ( const language of languages ) {
49- const virtualFile = language . createVirtualFile ( fileName , snapshot , languageId ) ;
45+ const virtualFile = language . createVirtualFile ( id , languageId , snapshot ) ;
5046 if ( virtualFile ) {
51- const source : Source = { fileName , languageId, snapshot, root : virtualFile , language } ;
52- sourceFiles . set ( key , source ) ;
47+ const source : SourceFile = { id : id , languageId, snapshot, root : virtualFile , language } ;
48+ sourceFileRegistry . set ( normalizeId ( id ) , source ) ;
5349 updateVirtualFiles ( source ) ;
5450 return virtualFile ; // created
5551 }
5652 }
57- sourceFiles . set ( key , { fileName , languageId, snapshot } ) ;
53+ sourceFileRegistry . set ( normalizeId ( id ) , { id : id , languageId, snapshot } ) ;
5854 } ,
59- deleteSource ( fileName : string ) {
60- const key = normalizePath ( fileName ) ;
61- const value = sourceFiles . get ( key ) ;
55+ deleteSourceFile ( id : string ) {
56+ const value = sourceFileRegistry . get ( normalizeId ( id ) ) ;
6257 if ( value ) {
6358 if ( value . language && value . root ) {
6459 value . language . deleteVirtualFile ?.( value . root ) ;
6560 }
66- sourceFiles . delete ( key ) ; // deleted
61+ sourceFileRegistry . delete ( normalizeId ( id ) ) ; // deleted
6762 deleteVirtualFiles ( value ) ;
6863 }
6964 } ,
@@ -79,62 +74,53 @@ export function createFileProvider(languages: Language[], sync: () => void) {
7974 virtualFileMaps . set ( virtualFile . snapshot , new Map ( ) ) ;
8075 }
8176
82- updateVirtualFileMaps ( virtualFile , sourceFileName => {
83- if ( sourceFileName ) {
84- const source = sourceFiles . get ( normalizePath ( sourceFileName ) ) ! ;
85- return [ sourceFileName , source . snapshot ] ;
77+ updateVirtualFileMaps ( virtualFile , sourceId => {
78+ if ( sourceId ) {
79+ const sourceFile = sourceFileRegistry . get ( normalizeId ( sourceId ) ) ! ;
80+ return [ sourceId , sourceFile . snapshot ] ;
8681 }
8782 else {
88- const source = virtualFiles . get ( normalizePath ( virtualFile . fileName ) ) ! . source ;
89- return [ source . fileName , source . snapshot ] ;
83+ const source = virtualFileRegistry . get ( normalizeId ( virtualFile . id ) ) ! . source ;
84+ return [ source . id , source . snapshot ] ;
9085 }
9186 } , virtualFileMaps . get ( virtualFile . snapshot ) ) ;
9287
9388 return virtualFileMaps . get ( virtualFile . snapshot ) ! ;
9489 } ,
95- getSource ( fileName : string ) {
96- sync ( ) ;
97- const key = normalizePath ( fileName ) ;
98- return sourceFiles . get ( key ) ;
99- } ,
100- hasSource ( fileName : string ) {
90+ getSourceFile ( id : string ) {
10191 sync ( ) ;
102- return sourceFiles . has ( normalizePath ( fileName ) ) ;
92+ return sourceFileRegistry . get ( normalizeId ( id ) ) ;
10393 } ,
104- hasVirtualFile ( fileName : string ) {
94+ getVirtualFile ( id : string ) {
10595 sync ( ) ;
106- return ! ! virtualFiles . get ( normalizePath ( fileName ) ) ;
107- } ,
108- getVirtualFile ( fileName : string ) {
109- sync ( ) ;
110- const sourceAndVirtual = virtualFiles . get ( normalizePath ( fileName ) ) ;
96+ const sourceAndVirtual = virtualFileRegistry . get ( normalizeId ( id ) ) ;
11197 if ( sourceAndVirtual ) {
11298 return [ sourceAndVirtual . virtualFile , sourceAndVirtual . source ] as const ;
11399 }
114100 return [ undefined , undefined ] as const ;
115101 } ,
116102 } ;
117103
118- function deleteVirtualFiles ( source : Source ) {
104+ function deleteVirtualFiles ( source : SourceFile ) {
119105 if ( source . root ) {
120106 forEachEmbeddedFile ( source . root , file => {
121- virtualFiles . delete ( normalizePath ( file . fileName ) ) ;
107+ virtualFileRegistry . delete ( normalizeId ( file . id ) ) ;
122108 } ) ;
123109 }
124110 }
125111
126- function updateVirtualFiles ( source : Source ) {
112+ function updateVirtualFiles ( source : SourceFile ) {
127113 if ( source . root ) {
128114 forEachEmbeddedFile ( source . root , file => {
129- virtualFiles . set ( normalizePath ( file . fileName ) , { virtualFile : file , source } ) ;
115+ virtualFileRegistry . set ( normalizeId ( file . id ) , { virtualFile : file , source } ) ;
130116 } ) ;
131117 }
132118 }
133119}
134120
135121export function updateVirtualFileMaps (
136122 virtualFile : VirtualFile ,
137- getSourceSnapshot : ( source : string | undefined ) => [ string , ts . IScriptSnapshot ] | undefined ,
123+ getSourceSnapshot : ( sourceUri : string | undefined ) => [ string , ts . IScriptSnapshot ] | undefined ,
138124 map : Map < string , [ ts . IScriptSnapshot , SourceMap < FileRangeCapabilities > ] > = new Map ( ) ,
139125) {
140126
@@ -165,7 +151,3 @@ export function forEachEmbeddedFile(file: VirtualFile, cb: (embedded: VirtualFil
165151 forEachEmbeddedFile ( embeddedFile , cb ) ;
166152 }
167153}
168-
169- function normalizePath ( fileName : string ) {
170- return fileName . replace ( / \\ / g, '/' ) . toLowerCase ( ) ;
171- }
0 commit comments