@@ -36,6 +36,29 @@ type LocationLink = {
3636 targetRange : PositionRange
3737}
3838
39+ class Cache < T > {
40+ private cache : T
41+ private dirty : boolean
42+ private updater : ( this : void , cache : T ) => T
43+
44+ constructor ( updater : ( this : void , cache : T ) => T , init : T ) {
45+ this . cache = init
46+ this . dirty = false
47+ this . updater = updater
48+ }
49+
50+ get ( ) : T {
51+ if ( this . dirty ) {
52+ this . cache = this . updater ( this . cache )
53+ }
54+ return this . cache
55+ }
56+
57+ invalidate ( ) : void {
58+ this . dirty = true
59+ }
60+ }
61+
3962const getDefaultExportOfSourceFile = (
4063 tc : ts . TypeChecker ,
4164 source : ts . SourceFile ,
@@ -77,7 +100,8 @@ export class Server {
77100 private workingDirectory : string
78101 private tsLangService : ts . LanguageService
79102 private projectDirManager : ProjectDirManager
80- private rootFilePaths : string [ ]
103+ private rootFilePaths : Cache < string [ ] >
104+ private rootTsFileCount : number
81105 private rootFilePathsVersion : number
82106 private configErrors : ts . Diagnostic [ ]
83107 private pendingAsyncTasksListeners : ( ( ) => void ) [ ] = [ ]
@@ -100,17 +124,18 @@ export class Server {
100124 this . logVerboseMessage ( `Opened component WXML: ${ fullPath } ` )
101125 const p = getWxmlConvertedTsPath ( fullPath )
102126 if ( p ) {
103- this . rootFilePaths . push ( p )
127+ this . rootFilePaths . get ( ) . push ( p )
104128 this . rootFilePathsVersion += 1
105129 }
106130 }
107131 this . projectDirManager . onEntranceFileRemoved = ( fullPath ) => {
108132 this . logVerboseMessage ( `Closed component WXML: ${ fullPath } ` )
109133 const p = getWxmlConvertedTsPath ( fullPath )
110134 if ( p ) {
111- const index = this . rootFilePaths . lastIndexOf ( p )
135+ const rootFilePaths = this . rootFilePaths . get ( )
136+ const index = rootFilePaths . lastIndexOf ( p )
112137 if ( index >= 0 ) {
113- this . rootFilePaths [ index ] = this . rootFilePaths . pop ( ) !
138+ rootFilePaths [ index ] = rootFilePaths . pop ( ) !
114139 this . rootFilePathsVersion += 1
115140 }
116141 }
@@ -126,6 +151,14 @@ export class Server {
126151 f . forEach ( ( f ) => f . call ( this ) )
127152 }
128153
154+ // handling root ts file changes
155+ const handleRootTsFileChanges = ( ) => {
156+ this . rootFilePathsVersion += 1
157+ this . rootFilePaths . invalidate ( )
158+ }
159+ this . projectDirManager . onScriptFileAdded = handleRootTsFileChanges
160+ this . projectDirManager . onScriptFileRemoved = handleRootTsFileChanges
161+
129162 // initialize ts language service
130163 /* eslint-disable @typescript-eslint/unbound-method, arrow-body-style */
131164 const configPath = tsc . findConfigFile ( this . projectPath , tsc . sys . fileExists , 'tsconfig.json' )
@@ -134,30 +167,40 @@ export class Server {
134167 if ( configPath !== undefined ) {
135168 // eslint-disable-next-line @typescript-eslint/unbound-method
136169 const configFile = tsc . readJsonConfigFile ( configPath , tsc . sys . readFile )
137- config = tsc . parseJsonSourceFileConfigFileContent (
138- configFile ,
139- {
140- useCaseSensitiveFileNames : false ,
141- readDirectory : tsc . sys . readDirectory ,
142- fileExists : tsc . sys . fileExists ,
143- readFile : tsc . sys . readFile ,
144- } ,
145- path . dirname ( configPath ) ,
146- { noEmit : true } ,
147- // undefined,
148- // undefined,
149- // [{ extension: '.wxml', isMixedContent: true, scriptKind: ts.ScriptKind.TS }],
150- )
170+ const getConfig = ( ) =>
171+ tsc . parseJsonSourceFileConfigFileContent (
172+ configFile ,
173+ {
174+ useCaseSensitiveFileNames : false ,
175+ readDirectory : tsc . sys . readDirectory ,
176+ fileExists : tsc . sys . fileExists ,
177+ readFile : tsc . sys . readFile ,
178+ } ,
179+ path . dirname ( configPath ) ,
180+ { noEmit : true } ,
181+ // undefined,
182+ // undefined,
183+ // [{ extension: '.wxml', isMixedContent: true, scriptKind: ts.ScriptKind.TS }],
184+ )
185+ config = getConfig ( )
186+ this . rootFilePaths = new Cache ( ( old ) => {
187+ const extra = old . slice ( this . rootTsFileCount )
188+ const ret = getConfig ( ) . fileNames
189+ this . rootTsFileCount = ret . length
190+ return ret . concat ( extra )
191+ } , config . fileNames )
192+ this . rootTsFileCount = config . fileNames . length
151193 } else {
152194 const compilerOptions = tsc . getDefaultCompilerOptions ( )
153195 config = {
154196 options : compilerOptions ,
155197 fileNames : [ ] ,
156198 errors : [ ] ,
157199 }
200+ this . rootFilePaths = new Cache ( ( x ) => x , [ ] as string [ ] )
201+ this . rootTsFileCount = 0
158202 }
159203 this . configErrors = config . errors
160- this . rootFilePaths = config . fileNames
161204 this . rootFilePathsVersion = 1
162205 const servicesHost : ts . LanguageServiceHost = {
163206 getCompilationSettings ( ) {
@@ -167,7 +210,7 @@ export class Server {
167210 return String ( this . rootFilePathsVersion )
168211 } ,
169212 getScriptFileNames : ( ) => {
170- return this . rootFilePaths
213+ return this . rootFilePaths . get ( )
171214 } ,
172215 getScriptVersion : ( fullPath ) => {
173216 return this . projectDirManager . getFileVersion ( fullPath ) ?. toString ( ) ?? ''
0 commit comments