@@ -21,7 +21,7 @@ import { SwiftToolchain } from "./toolchain/toolchain";
2121import { BuildFlags } from "./toolchain/BuildFlags" ;
2222
2323/** Swift Package Manager contents */
24- export interface PackageContents {
24+ interface PackageContents {
2525 name : string ;
2626 products : Product [ ] ;
2727 dependencies : Dependency [ ] ;
@@ -184,8 +184,10 @@ function isError(state: SwiftPackageState): state is Error {
184184/**
185185 * Class holding Swift Package Manager Package
186186 */
187- export class SwiftPackage implements PackageContents {
187+ export class SwiftPackage {
188188 public plugins : PackagePlugin [ ] = [ ] ;
189+ private _contents : SwiftPackageState | undefined ;
190+
189191 /**
190192 * SwiftPackage Constructor
191193 * @param folder folder package is in
@@ -194,7 +196,7 @@ export class SwiftPackage implements PackageContents {
194196 */
195197 private constructor (
196198 readonly folder : vscode . Uri ,
197- private contents : SwiftPackageState ,
199+ private contentsPromise : Promise < SwiftPackageState > ,
198200 public resolved : PackageResolved | undefined ,
199201 private workspaceState : WorkspaceState | undefined
200202 ) { }
@@ -208,10 +210,34 @@ export class SwiftPackage implements PackageContents {
208210 folder : vscode . Uri ,
209211 toolchain : SwiftToolchain
210212 ) : 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+ } ) ;
215241 }
216242
217243 /**
@@ -326,7 +352,9 @@ export class SwiftPackage implements PackageContents {
326352
327353 /** Reload swift package */
328354 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 ) ;
330358 }
331359
332360 /** Reload Package.resolved file */
@@ -343,31 +371,26 @@ export class SwiftPackage implements PackageContents {
343371 }
344372
345373 /** 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 ) ) ;
348376 }
349377
350378 /** 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 ) ) ;
357381 }
358382
359383 /** 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 ) ;
362386 }
363387
364- public rootDependencies ( ) : ResolvedDependency [ ] {
388+ public get rootDependencies ( ) : Promise < ResolvedDependency [ ] > {
365389 // Correlate the root dependencies found in the Package.swift with their
366390 // 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 ) )
369393 ) ;
370- return result ;
371394 }
372395
373396 private resolveDependencyAgainstWorkspaceState ( dependency : Dependency ) : ResolvedDependency {
@@ -443,55 +466,70 @@ export class SwiftPackage implements PackageContents {
443466 }
444467 }
445468
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 ?? "" ) ;
449472 }
450473
451474 /** 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 ?? [ ] ) ;
454477 }
455478
456479 /** 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 ?? [ ] ) ;
459482 }
460483
461484 /** 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 ?? [ ] ) ;
464487 }
465488
466489 /** 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+ ) ;
469494 }
470495
471496 /** 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 ?? [ ] ;
474510 }
475511
476512 /**
477513 * Return array of targets of a certain type
478514 * @param type Type of target
479515 * @returns Array of targets
480516 */
481- getTargets ( type ?: TargetType ) : Target [ ] {
517+ async getTargets ( type ?: TargetType ) : Promise < Target [ ] > {
482518 if ( type === undefined ) {
483519 return this . targets ;
484520 } else {
485- return this . targets . filter ( target => target . type === type ) ;
521+ return this . targets . then ( targets => targets . filter ( target => target . type === type ) ) ;
486522 }
487523 }
488524
489525 /**
490526 * Get target for file
491527 */
492- getTarget ( file : string ) : Target | undefined {
528+ async getTarget ( file : string ) : Promise < Target | undefined > {
493529 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+ ) ;
495533 }
496534
497535 private static trimStdout ( stdout : string ) : string {
0 commit comments