@@ -21,7 +21,7 @@ import { SwiftToolchain } from "./toolchain/toolchain";
21
21
import { BuildFlags } from "./toolchain/BuildFlags" ;
22
22
23
23
/** Swift Package Manager contents */
24
- export interface PackageContents {
24
+ interface PackageContents {
25
25
name : string ;
26
26
products : Product [ ] ;
27
27
dependencies : Dependency [ ] ;
@@ -184,8 +184,10 @@ function isError(state: SwiftPackageState): state is Error {
184
184
/**
185
185
* Class holding Swift Package Manager Package
186
186
*/
187
- export class SwiftPackage implements PackageContents {
187
+ export class SwiftPackage {
188
188
public plugins : PackagePlugin [ ] = [ ] ;
189
+ private _contents : SwiftPackageState | undefined ;
190
+
189
191
/**
190
192
* SwiftPackage Constructor
191
193
* @param folder folder package is in
@@ -194,7 +196,7 @@ export class SwiftPackage implements PackageContents {
194
196
*/
195
197
private constructor (
196
198
readonly folder : vscode . Uri ,
197
- private contents : SwiftPackageState ,
199
+ private contentsPromise : Promise < SwiftPackageState > ,
198
200
public resolved : PackageResolved | undefined ,
199
201
private workspaceState : WorkspaceState | undefined
200
202
) { }
@@ -208,10 +210,34 @@ export class SwiftPackage implements PackageContents {
208
210
folder : vscode . Uri ,
209
211
toolchain : SwiftToolchain
210
212
) : Promise < SwiftPackage > {
211
- const contents = await SwiftPackage . loadPackage ( folder , toolchain ) ;
212
- const resolved = await SwiftPackage . loadPackageResolved ( folder ) ;
213
- const workspaceState = await SwiftPackage . loadWorkspaceState ( folder ) ;
214
- return new SwiftPackage ( folder , contents , resolved , workspaceState ) ;
213
+ const [ resolved , workspaceState ] = await Promise . all ( [
214
+ SwiftPackage . loadPackageResolved ( folder ) ,
215
+ SwiftPackage . loadWorkspaceState ( folder ) ,
216
+ ] ) ;
217
+ return new SwiftPackage (
218
+ folder ,
219
+ SwiftPackage . loadPackage ( folder , toolchain ) ,
220
+ resolved ,
221
+ workspaceState
222
+ ) ;
223
+ }
224
+
225
+ /**
226
+ * Returns the package state once it has loaded.
227
+ * A snapshot of the state is stored in `_contents` after initial resolution.
228
+ */
229
+ private get contents ( ) : Promise < SwiftPackageState > {
230
+ return this . contentsPromise . then ( contents => {
231
+ // If `reload` is called immediately its possible for it to resolve
232
+ // before the initial contentsPromise resolution. In that case return
233
+ // the newer loaded `_contents`.
234
+ if ( this . _contents === undefined ) {
235
+ this . _contents = contents ;
236
+ return contents ;
237
+ } else {
238
+ return this . _contents ;
239
+ }
240
+ } ) ;
215
241
}
216
242
217
243
/**
@@ -326,7 +352,9 @@ export class SwiftPackage implements PackageContents {
326
352
327
353
/** Reload swift package */
328
354
public async reload ( toolchain : SwiftToolchain ) {
329
- this . contents = await SwiftPackage . loadPackage ( this . folder , toolchain ) ;
355
+ const loadedContents = await SwiftPackage . loadPackage ( this . folder , toolchain ) ;
356
+ this . _contents = loadedContents ;
357
+ this . contentsPromise = Promise . resolve ( loadedContents ) ;
330
358
}
331
359
332
360
/** Reload Package.resolved file */
@@ -343,31 +371,26 @@ export class SwiftPackage implements PackageContents {
343
371
}
344
372
345
373
/** Return if has valid contents */
346
- public get isValid ( ) : boolean {
347
- return isPackage ( this . contents ) ;
374
+ public get isValid ( ) : Promise < boolean > {
375
+ return this . contents . then ( contents => isPackage ( contents ) ) ;
348
376
}
349
377
350
378
/** Load error */
351
- public get error ( ) : Error | undefined {
352
- if ( isError ( this . contents ) ) {
353
- return this . contents ;
354
- } else {
355
- return undefined ;
356
- }
379
+ public get error ( ) : Promise < Error | undefined > {
380
+ return this . contents . then ( contents => ( isError ( contents ) ? contents : undefined ) ) ;
357
381
}
358
382
359
383
/** Did we find a Package.swift */
360
- public get foundPackage ( ) : boolean {
361
- return this . contents !== undefined ;
384
+ public get foundPackage ( ) : Promise < boolean > {
385
+ return this . contents . then ( contents => contents !== undefined ) ;
362
386
}
363
387
364
- public rootDependencies ( ) : ResolvedDependency [ ] {
388
+ public get rootDependencies ( ) : Promise < ResolvedDependency [ ] > {
365
389
// Correlate the root dependencies found in the Package.swift with their
366
390
// checked out versions in the workspace-state.json.
367
- const result = this . dependencies . map ( dependency =>
368
- this . resolveDependencyAgainstWorkspaceState ( dependency )
391
+ return this . dependencies . then ( dependencies =>
392
+ dependencies . map ( dependency => this . resolveDependencyAgainstWorkspaceState ( dependency ) )
369
393
) ;
370
- return result ;
371
394
}
372
395
373
396
private resolveDependencyAgainstWorkspaceState ( dependency : Dependency ) : ResolvedDependency {
@@ -443,55 +466,70 @@ export class SwiftPackage implements PackageContents {
443
466
}
444
467
}
445
468
446
- /** name of Swift Package */
447
- get name ( ) : string {
448
- return ( this . contents as PackageContents ) ?. name ?? "" ;
469
+ /** getName of Swift Package */
470
+ get name ( ) : Promise < string > {
471
+ return this . contents . then ( contents => ( contents as PackageContents ) ?. name ?? "" ) ;
449
472
}
450
473
451
474
/** array of products in Swift Package */
452
- get products ( ) : Product [ ] {
453
- return ( this . contents as PackageContents ) ?. products ?? [ ] ;
475
+ private get products ( ) : Promise < Product [ ] > {
476
+ return this . contents . then ( contents => ( contents as PackageContents ) ?. products ?? [ ] ) ;
454
477
}
455
478
456
479
/** array of dependencies in Swift Package */
457
- get dependencies ( ) : Dependency [ ] {
458
- return ( this . contents as PackageContents ) ?. dependencies ?? [ ] ;
480
+ get dependencies ( ) : Promise < Dependency [ ] > {
481
+ return this . contents . then ( contents => ( contents as PackageContents ) ?. dependencies ?? [ ] ) ;
459
482
}
460
483
461
484
/** array of targets in Swift Package */
462
- get targets ( ) : Target [ ] {
463
- return ( this . contents as PackageContents ) ?. targets ?? [ ] ;
485
+ get targets ( ) : Promise < Target [ ] > {
486
+ return this . contents . then ( contents => ( contents as PackageContents ) ?. targets ?? [ ] ) ;
464
487
}
465
488
466
489
/** array of executable products in Swift Package */
467
- get executableProducts ( ) : Product [ ] {
468
- return this . products . filter ( product => product . type . executable !== undefined ) ;
490
+ get executableProducts ( ) : Promise < Product [ ] > {
491
+ return this . products . then ( products =>
492
+ products . filter ( product => product . type . executable !== undefined )
493
+ ) ;
469
494
}
470
495
471
496
/** array of library products in Swift Package */
472
- get libraryProducts ( ) : Product [ ] {
473
- return this . products . filter ( product => product . type . library !== undefined ) ;
497
+ get libraryProducts ( ) : Promise < Product [ ] > {
498
+ return this . products . then ( products =>
499
+ products . filter ( product => product . type . library !== undefined )
500
+ ) ;
501
+ }
502
+
503
+ /**
504
+ * Array of targets in Swift Package. The targets may not be loaded yet.
505
+ * It is preferable to use the `targets` property that returns a promise that
506
+ * returns the targets when they're guarenteed to be resolved.
507
+ **/
508
+ get currentTargets ( ) : Target [ ] {
509
+ return ( this . _contents as unknown as { targets : Target [ ] } ) ?. targets ?? [ ] ;
474
510
}
475
511
476
512
/**
477
513
* Return array of targets of a certain type
478
514
* @param type Type of target
479
515
* @returns Array of targets
480
516
*/
481
- getTargets ( type ?: TargetType ) : Target [ ] {
517
+ async getTargets ( type ?: TargetType ) : Promise < Target [ ] > {
482
518
if ( type === undefined ) {
483
519
return this . targets ;
484
520
} else {
485
- return this . targets . filter ( target => target . type === type ) ;
521
+ return this . targets . then ( targets => targets . filter ( target => target . type === type ) ) ;
486
522
}
487
523
}
488
524
489
525
/**
490
526
* Get target for file
491
527
*/
492
- getTarget ( file : string ) : Target | undefined {
528
+ async getTarget ( file : string ) : Promise < Target | undefined > {
493
529
const filePath = path . relative ( this . folder . fsPath , file ) ;
494
- return this . targets . find ( target => isPathInsidePath ( filePath , target . path ) ) ;
530
+ return this . targets . then ( targets =>
531
+ targets . find ( target => isPathInsidePath ( filePath , target . path ) )
532
+ ) ;
495
533
}
496
534
497
535
private static trimStdout ( stdout : string ) : string {
0 commit comments