@@ -17,10 +17,10 @@ import {
17
17
classNameRegex ,
18
18
compileErrorMsg ,
19
19
cspAppsForUri ,
20
- CurrentBinaryFile ,
21
20
currentFile ,
22
21
currentFileFromContent ,
23
22
CurrentTextFile ,
23
+ EitherCurrentFile ,
24
24
exportedUris ,
25
25
getWsFolder ,
26
26
handleError ,
@@ -57,7 +57,7 @@ async function compileFlags(): Promise<string> {
57
57
* @param force If passed true, use server mtime.
58
58
* @return mtime timestamp or -1.
59
59
*/
60
- export async function checkChangedOnServer ( file : CurrentTextFile | CurrentBinaryFile , force = false ) : Promise < number > {
60
+ export async function checkChangedOnServer ( file : EitherCurrentFile , force = false ) : Promise < number > {
61
61
if ( ! file || ! file . uri || schemas . includes ( file . uri . scheme ) ) {
62
62
return - 1 ;
63
63
}
@@ -88,7 +88,7 @@ export async function checkChangedOnServer(file: CurrentTextFile | CurrentBinary
88
88
}
89
89
90
90
export async function importFile (
91
- file : CurrentTextFile | CurrentBinaryFile ,
91
+ file : EitherCurrentFile ,
92
92
ignoreConflict ?: boolean ,
93
93
skipDeplCheck = false
94
94
) : Promise < any > {
@@ -213,61 +213,79 @@ function updateOthers(others: string[], baseUri: vscode.Uri) {
213
213
} ) ;
214
214
}
215
215
216
- export async function loadChanges ( files : ( CurrentTextFile | CurrentBinaryFile ) [ ] ) : Promise < any > {
217
- if ( ! files . length ) {
218
- return ;
219
- }
216
+ /**
217
+ * Reload the contents of `files` from the server. This will also a trigger a
218
+ * refresh of in-memory copies of "other" documents related to `files`. Files
219
+ * in the `onlyUpdateOthersFiles` array will not have their contents reloaded.
220
+ * Only their "other" documents will be refreshed.
221
+ */
222
+ export async function loadChanges (
223
+ files : EitherCurrentFile [ ] ,
224
+ onlyUpdateOthersFiles : EitherCurrentFile [ ] = [ ]
225
+ ) : Promise < void > {
226
+ if ( ! files ?. length ) return ;
220
227
const api = new AtelierAPI ( files [ 0 ] . uri ) ;
221
228
// Use allSettled so we attempt to load changes for all files, even if some fail
222
- return api . actionIndex ( files . map ( ( f ) => f . name ) ) . then ( ( data ) =>
223
- Promise . allSettled (
224
- data . result . content . map ( async ( doc ) => {
225
- if ( doc . status . length ) return ;
226
- const file = files . find ( ( f ) => f . name == doc . name ) ;
227
- const mtime = Number ( new Date ( doc . ts + "Z" ) ) ;
228
- workspaceState . update ( `${ file . uniqueId } :mtime` , mtime > 0 ? mtime : undefined ) ;
229
- if ( notIsfs ( file . uri ) ) {
230
- const content = await api . getDoc ( file . name , file . uri ) . then ( ( data ) => data . result . content ) ;
231
- exportedUris . add ( file . uri . toString ( ) ) ; // Set optimistically
232
- await vscode . workspace . fs
233
- . writeFile (
234
- file . uri ,
235
- Buffer . isBuffer ( content )
236
- ? content
237
- : new TextEncoder ( ) . encode (
238
- content . join (
239
- ( ( < CurrentTextFile > file ) ?. eol ?? vscode . EndOfLine . LF ) == vscode . EndOfLine . CRLF ? "\r\n" : "\n"
240
- )
241
- )
242
- )
243
- . then ( undefined , ( e ) => {
244
- // Save failed, so remove this URI from the set
245
- exportedUris . delete ( file . uri . toString ( ) ) ;
246
- // Re-throw the error
247
- throw e ;
248
- } ) ;
249
- if ( isClassOrRtn ( file . uri ) ) {
250
- // Update the document index
251
- updateIndexForDocument ( file . uri , undefined , undefined , content ) ;
229
+ await api
230
+ . actionIndex ( Array . from ( new Set ( files . map ( ( f ) => f . name ) . concat ( onlyUpdateOthersFiles . map ( ( f ) => f . name ) ) ) ) )
231
+ . then ( ( data ) =>
232
+ Promise . allSettled (
233
+ data . result . content . map ( async ( doc ) => {
234
+ if ( doc . status . length ) return ;
235
+ let file = files . find ( ( f ) => f . name == doc . name ) ;
236
+ if ( file ) {
237
+ // This is a file that requires a content reload
238
+ if ( notIsfs ( file . uri ) ) {
239
+ const mtime = Number ( new Date ( doc . ts + "Z" ) ) ;
240
+ workspaceState . update ( `${ file . uniqueId } :mtime` , mtime > 0 ? mtime : undefined ) ;
241
+ const content = await api . getDoc ( file . name , file . uri ) . then ( ( data ) => data . result . content ) ;
242
+ exportedUris . add ( file . uri . toString ( ) ) ; // Set optimistically
243
+ await vscode . workspace . fs
244
+ . writeFile (
245
+ file . uri ,
246
+ Buffer . isBuffer ( content )
247
+ ? content
248
+ : new TextEncoder ( ) . encode (
249
+ content . join (
250
+ ( ( < CurrentTextFile > file ) ?. eol ?? vscode . EndOfLine . LF ) == vscode . EndOfLine . CRLF ? "\r\n" : "\n"
251
+ )
252
+ )
253
+ )
254
+ . then ( undefined , ( e ) => {
255
+ // Save failed, so remove this URI from the set
256
+ exportedUris . delete ( file . uri . toString ( ) ) ;
257
+ // Re-throw the error
258
+ throw e ;
259
+ } ) ;
260
+ if ( isClassOrRtn ( file . uri ) ) {
261
+ // Update the document index
262
+ updateIndexForDocument ( file . uri , undefined , undefined , content ) ;
263
+ }
264
+ } else {
265
+ fileSystemProvider . fireFileChanged ( file . uri ) ;
266
+ }
267
+ } else {
268
+ // The contents of this file did not change, but its "other" documents still need to be updated
269
+ file = onlyUpdateOthersFiles . find ( ( f ) => f . name == doc . name ) ;
270
+ if ( ! file ) return ;
252
271
}
253
- } else if ( filesystemSchemas . includes ( file . uri . scheme ) ) {
254
- fileSystemProvider . fireFileChanged ( file . uri ) ;
255
- }
256
- updateOthers ( doc . others , file . uri ) ;
257
- } )
258
- )
259
- ) ;
272
+ updateOthers ( doc . others , file . uri ) ;
273
+ } )
274
+ )
275
+ ) ;
260
276
}
261
277
262
- export async function compile ( docs : ( CurrentTextFile | CurrentBinaryFile ) [ ] , flags ?: string ) : Promise < any > {
278
+ export async function compile ( docs : EitherCurrentFile [ ] , flags ?: string ) : Promise < any > {
263
279
const wsFolder = vscode . workspace . getWorkspaceFolder ( docs [ 0 ] . uri ) ;
264
280
const conf = vscode . workspace . getConfiguration ( "objectscript" , wsFolder || docs [ 0 ] . uri ) ;
265
281
flags = flags || conf . get ( "compileFlags" ) ;
266
282
const api = new AtelierAPI ( docs [ 0 ] . uri ) ;
267
283
const docNames = docs . map ( ( d ) => d . name ) ;
268
- // Determine the line ending to use for other documents affected
284
+ // Determine the line ending to use for documents affected
269
285
// by compilation so we don't need to read their contents
270
286
const eol = ( < CurrentTextFile > docs . find ( ( d ) => ( < CurrentTextFile > d ) ?. eol ) ) ?. eol ?? vscode . EndOfLine . LF ;
287
+ const docsToReload : EitherCurrentFile [ ] = [ ] ;
288
+ const docsToRefreshOthers : EitherCurrentFile [ ] = [ ...docs ] ;
271
289
return vscode . window
272
290
. withProgress (
273
291
{
@@ -285,13 +303,18 @@ export async function compile(docs: (CurrentTextFile | CurrentBinaryFile)[], fla
285
303
} else if ( ! conf . get ( "suppressCompileMessages" ) ) {
286
304
vscode . window . showInformationMessage ( `${ info } Compilation succeeded.` , "Dismiss" ) ;
287
305
}
288
- if ( wsFolder ) {
289
- // Make sure that we update the content for any
290
- // other documents affected by this compilation
291
- data . result . content . forEach ( ( f ) => {
292
- if ( docNames . includes ( f . name ) ) return ;
306
+ data . result . content . forEach ( ( f ) => {
307
+ // Reload the contents of files that were changed by compilation
308
+ if ( docNames . includes ( f . name ) ) {
309
+ docsToReload . push (
310
+ ...docsToRefreshOthers . splice (
311
+ docsToRefreshOthers . findIndex ( ( d ) => d . name == f . name ) ,
312
+ 1
313
+ )
314
+ ) ;
315
+ } else if ( wsFolder ) {
293
316
getUrisForDocument ( f . name , wsFolder ) . forEach ( ( u ) => {
294
- docs . push ( {
317
+ docsToReload . push ( {
295
318
name : f . name ,
296
319
uri : u ,
297
320
uniqueId : `${ wsFolder . name } :${ f . name } ` ,
@@ -302,17 +325,14 @@ export async function compile(docs: (CurrentTextFile | CurrentBinaryFile)[], fla
302
325
content : "" ,
303
326
} ) ;
304
327
} ) ;
305
- } ) ;
306
- }
307
- return docs ;
308
- } )
309
- . catch ( ( ) => {
310
- compileErrorMsg ( conf ) ;
311
- // Always fetch server changes, even when compile failed or got cancelled
312
- return docs ;
328
+ }
329
+ } ) ;
313
330
} )
331
+ . catch ( ( ) => compileErrorMsg ( conf ) )
314
332
)
315
- . then ( loadChanges ) ;
333
+ . then ( ( ) => {
334
+ return loadChanges ( docsToReload , docsToRefreshOthers ) ;
335
+ } ) ;
316
336
}
317
337
318
338
export async function importAndCompile (
@@ -429,7 +449,7 @@ export async function namespaceCompile(askFlags = false): Promise<any> {
429
449
}
430
450
431
451
async function importFiles ( files : vscode . Uri [ ] , noCompile = false ) {
432
- const toCompile : ( CurrentTextFile | CurrentBinaryFile ) [ ] = [ ] ;
452
+ const toCompile : EitherCurrentFile [ ] = [ ] ;
433
453
const rateLimiter = new RateLimiter ( 50 ) ;
434
454
await Promise . allSettled < void > (
435
455
files . map ( ( uri ) =>
0 commit comments