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