Skip to content

Increase adoption of async in manifest loading code #7724

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Examples/package-info/Sources/package-info/example.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct Example {

let package = try await workspace.loadRootPackage(at: packagePath, observabilityScope: observability.topScope)

let graph = try workspace.loadPackageGraph(rootPath: packagePath, observabilityScope: observability.topScope)
let graph = try await workspace.loadPackageGraph(rootPath: packagePath, observabilityScope: observability.topScope)

// EXAMPLES
// ========
Expand Down
31 changes: 31 additions & 0 deletions Sources/Basics/Graph/GraphAlgorithms.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,34 @@ public func depthFirstSearch<T: Hashable>(
}
}
}

package func asyncDepthFirstSearch<T: Hashable>(
_ nodes: [T],
successors: (T) async throws -> [T],
onUnique: (T) -> Void,
onDuplicate: (T, T) -> Void
) async rethrows {
var stack = OrderedSet<T>()
var visited = Set<T>()

for node in nodes {
precondition(stack.isEmpty)
stack.append(node)

while !stack.isEmpty {
let curr = stack.removeLast()

let visitResult = visited.insert(curr)
if visitResult.inserted {
onUnique(curr)
} else {
onDuplicate(visitResult.memberAfterInsert, curr)
continue
}

for succ in try await successors(curr) {
stack.append(succ)
}
}
}
}
28 changes: 28 additions & 0 deletions Sources/Basics/Observability.swift
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,34 @@ extension DiagnosticsEmitterProtocol {
}
}

/// trap a throwing closure, emitting diagnostics on error and returning boolean representing success
@discardableResult
public func asyncTrap(_ closure: () async throws -> Void) async -> Bool {
do {
try await closure()
return true
} catch Diagnostics.fatalError {
// FIXME: (diagnostics) deprecate this with Diagnostics.fatalError
return false
} catch {
self.emit(error)
return false
}
}

/// trap a throwing closure, emitting diagnostics on error and returning the value returned by the closure
public func asyncTrap<T>(_ closure: () async throws -> T) async -> T? {
do {
return try await closure()
} catch Diagnostics.fatalError {
// FIXME: (diagnostics) deprecate this with Diagnostics.fatalError
return nil
} catch {
self.emit(error)
return nil
}
}

/// If `underlyingError` is not `nil`, its human-readable description is interpolated with `message`,
/// otherwise `message` itself is returned.
private func makeMessage(from message: String, underlyingError: Error?) -> String {
Expand Down
8 changes: 4 additions & 4 deletions Sources/CoreCommands/BuildSystemSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ private struct NativeBuildSystemFactory: BuildSystemFactory {
cacheBuildManifest: Bool,
productsBuildParameters: BuildParameters?,
toolsBuildParameters: BuildParameters?,
packageGraphLoader: (() throws -> ModulesGraph)?,
packageGraphLoader: (() async throws -> ModulesGraph)?,
outputStream: OutputByteStream?,
logLevel: Diagnostic.Severity?,
observabilityScope: ObservabilityScope?
) throws -> any BuildSystem {
let rootPackageInfo = try swiftCommandState.getRootPackageInformation()
) async throws -> any BuildSystem {
let rootPackageInfo = try await swiftCommandState.getRootPackageInformation()
let testEntryPointPath = productsBuildParameters?.testingParameters.testProductStyle.explicitlySpecifiedEntryPointPath
return try BuildOperation(
productsBuildParameters: try productsBuildParameters ?? self.swiftCommandState.productsBuildParameters,
toolsBuildParameters: try toolsBuildParameters ?? self.swiftCommandState.toolsBuildParameters,
cacheBuildManifest: cacheBuildManifest && self.swiftCommandState.canUseCachedBuildManifest(),
packageGraphLoader: packageGraphLoader ?? {
try self.swiftCommandState.loadPackageGraph(
try await self.swiftCommandState.loadPackageGraph(
explicitProduct: explicitProduct,
traitConfiguration: traitConfiguration,
testEntryPointPath: testEntryPointPath
Expand Down
17 changes: 7 additions & 10 deletions Sources/CoreCommands/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ public struct TestLibraryOptions: ParsableArguments {
/// Whether to enable support for swift-testing.
public func enableSwiftTestingLibrarySupport(
swiftCommandState: SwiftCommandState
) throws -> Bool {
) async throws -> Bool {
// Honor the user's explicit command-line selection, if any.
if let callerSuppliedValue = explicitlyEnableSwiftTestingLibrarySupport {
return callerSuppliedValue
Expand All @@ -596,13 +596,10 @@ public struct TestLibraryOptions: ParsableArguments {
// If the active package has a dependency on swift-testing, automatically enable support for it so that extra steps are not needed.
let workspace = try swiftCommandState.getActiveWorkspace()
let root = try swiftCommandState.getWorkspaceRoot()
let rootManifests = try temp_await {
workspace.loadRootManifests(
packages: root.packages,
observabilityScope: swiftCommandState.observabilityScope,
completion: $0
)
}
let rootManifests = await workspace.loadRootManifests(
packages: root.packages,
observabilityScope: swiftCommandState.observabilityScope
)

// Is swift-testing among the dependencies of the package being built?
// If so, enable support.
Expand Down Expand Up @@ -634,13 +631,13 @@ public struct TestLibraryOptions: ParsableArguments {
/// Get the set of enabled testing libraries.
public func enabledTestingLibraries(
swiftCommandState: SwiftCommandState
) throws -> Set<BuildParameters.Testing.Library> {
) async throws -> Set<BuildParameters.Testing.Library> {
var result = Set<BuildParameters.Testing.Library>()

if enableXCTestSupport {
result.insert(.xctest)
}
if try enableSwiftTestingLibrarySupport(swiftCommandState: swiftCommandState) {
if try await enableSwiftTestingLibrarySupport(swiftCommandState: swiftCommandState) {
result.insert(.swiftTesting)
}

Expand Down
28 changes: 14 additions & 14 deletions Sources/CoreCommands/SwiftCommandState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -480,16 +480,16 @@ public final class SwiftCommandState {
return workspace
}

public func getRootPackageInformation() throws -> (dependencies: [PackageIdentity: [PackageIdentity]], targets: [PackageIdentity: [String]]) {
public func getRootPackageInformation() async throws -> (
dependencies: [PackageIdentity: [PackageIdentity]],
targets: [PackageIdentity: [String]]
) {
let workspace = try self.getActiveWorkspace()
let root = try self.getWorkspaceRoot()
let rootManifests = try temp_await {
workspace.loadRootManifests(
packages: root.packages,
observabilityScope: self.observabilityScope,
completion: $0
)
}
let rootManifests = await workspace.loadRootManifests(
packages: root.packages,
observabilityScope: self.observabilityScope
)

var identities = [PackageIdentity: [PackageIdentity]]()
var targets = [PackageIdentity: [String]]()
Expand Down Expand Up @@ -587,11 +587,11 @@ public final class SwiftCommandState {
}

/// Resolve the dependencies.
public func resolve() throws {
public func resolve() async throws {
let workspace = try getActiveWorkspace()
let root = try getWorkspaceRoot()

try workspace.resolve(
try await workspace.resolve(
root: root,
forceResolution: false,
forceResolvedVersions: options.resolver.forceResolvedVersions,
Expand All @@ -614,8 +614,8 @@ public final class SwiftCommandState {
public func loadPackageGraph(
explicitProduct: String? = nil,
testEntryPointPath: AbsolutePath? = nil
) throws -> ModulesGraph {
try self.loadPackageGraph(
) async throws -> ModulesGraph {
try await self.loadPackageGraph(
explicitProduct: explicitProduct,
traitConfiguration: nil,
testEntryPointPath: testEntryPointPath
Expand All @@ -632,12 +632,12 @@ public final class SwiftCommandState {
explicitProduct: String? = nil,
traitConfiguration: TraitConfiguration? = nil,
testEntryPointPath: AbsolutePath? = nil
) throws -> ModulesGraph {
) async throws -> ModulesGraph {
do {
let workspace = try getActiveWorkspace()

// Fetch and load the package graph.
let graph = try workspace.loadPackageGraph(
let graph = try await workspace.loadPackageGraph(
rootInput: getWorkspaceRoot(),
explicitProduct: explicitProduct,
traitConfiguration: traitConfiguration,
Expand Down
8 changes: 4 additions & 4 deletions Sources/SPMBuildCore/BuildSystem/BuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ public protocol BuildSystemFactory {
cacheBuildManifest: Bool,
productsBuildParameters: BuildParameters?,
toolsBuildParameters: BuildParameters?,
packageGraphLoader: (() throws -> ModulesGraph)?,
packageGraphLoader: (() async throws -> ModulesGraph)?,
outputStream: OutputByteStream?,
logLevel: Diagnostic.Severity?,
observabilityScope: ObservabilityScope?
) throws -> any BuildSystem
) async throws -> any BuildSystem
}

public struct BuildSystemProvider {
Expand All @@ -135,11 +135,11 @@ public struct BuildSystemProvider {
outputStream: OutputByteStream? = .none,
logLevel: Diagnostic.Severity? = .none,
observabilityScope: ObservabilityScope? = .none
) throws -> any BuildSystem {
) async throws -> any BuildSystem {
guard let buildSystemFactory = self.providers[kind] else {
throw Errors.buildSystemProviderNotRegistered(kind: kind)
}
return try buildSystemFactory.makeBuildSystem(
return try await buildSystemFactory.makeBuildSystem(
explicitProduct: explicitProduct,
traitConfiguration: traitConfiguration,
cacheBuildManifest: cacheBuildManifest,
Expand Down
Loading