Skip to content

Commit 211be8c

Browse files
authored
[NFC] Remove redundant DependencyResolver protocol (#7127)
### Motivation: This protocol doesn't define any requirements and was used for nemaspacing a single tuple typealias. Instead of typealiasing this fairly complex and pervasively used tuple, we should define a separate struct for it. Then the protocol itself can be removed as completely unused. ### Modifications: Defined new `struct DependencyResolverBinding` with cleanly named fields, which now avoids expressions that look like `binding.binding` and re-declaration of this tuple in multiple places. One other `typealias` in `protocol DependencyResolver` is unused, thus the whole protocol is unused and now can be removed. Also used this as an opportunity to clean up file naming and directory layout in the `PackageGraph` module. ### Result: This confusing protocol is removed from the codebase. Readability is improved with explicit struct field names instead of ad-hoc tuple use. Directory layout makes it more obvious the purpose of specific files for potential new contributors and for existing contributors when reviewing code retrospectively.
1 parent ce159ca commit 211be8c

20 files changed

+115
-80
lines changed

Sources/PackageGraph/CMakeLists.txt

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
add_library(PackageGraph
1010
BoundVersion.swift
1111
DependencyMirrors.swift
12-
DependencyResolutionNode.swift
13-
DependencyResolver.swift
1412
Diagnostics.swift
1513
GraphLoadingNode.swift
1614
ModuleAliasTracker.swift
@@ -21,17 +19,21 @@ add_library(PackageGraph
2119
PackageModel+Extensions.swift
2220
PackageRequirement.swift
2321
PinsStore.swift
24-
PubGrub/Assignment.swift
25-
PubGrub/ContainerProvider.swift
26-
PubGrub/DiagnosticReportBuilder.swift
27-
PubGrub/Incompatibility.swift
28-
PubGrub/PartialSolution.swift
29-
PubGrub/PubGrubDependencyResolver.swift
30-
PubGrub/PubGrubPackageContainer.swift
31-
PubGrub/Term.swift
32-
ResolvedPackage.swift
33-
ResolvedProduct.swift
34-
ResolvedTarget.swift
22+
Resolution/PubGrub/Assignment.swift
23+
Resolution/PubGrub/ContainerProvider.swift
24+
Resolution/PubGrub/DiagnosticReportBuilder.swift
25+
Resolution/PubGrub/Incompatibility.swift
26+
Resolution/PubGrub/PartialSolution.swift
27+
Resolution/PubGrub/PubGrubDependencyResolver.swift
28+
Resolution/PubGrub/PubGrubPackageContainer.swift
29+
Resolution/PubGrub/Term.swift
30+
Resolution/DependencyResolutionNode.swift
31+
Resolution/DependencyResolverBinding.swift
32+
Resolution/DependencyResolverDelegate.swift
33+
Resolution/DependencyResolverError.swift
34+
Resolution/ResolvedPackage.swift
35+
Resolution/ResolvedProduct.swift
36+
Resolution/ResolvedTarget.swift
3537
Version+Extensions.swift
3638
VersionSetSpecifier.swift)
3739
target_link_libraries(PackageGraph PUBLIC

Sources/PackageGraph/GraphLoadingNode.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import PackageModel
1818
///
1919
/// This node uses the product filter that was already finalized during resolution.
2020
///
21-
/// - SeeAlso: DependencyResolutionNode
21+
/// - SeeAlso: ``DependencyResolutionNode``
2222
public struct GraphLoadingNode: Equatable, Hashable {
2323

2424
/// The package identity.

Sources/PackageGraph/DependencyResolutionNode.swift renamed to Sources/PackageGraph/Resolution/DependencyResolutionNode.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import struct TSCUtility.Version
1818
///
1919
/// See the documentation of each case for more detailed descriptions of each kind and how they interact.
2020
///
21-
/// - SeeAlso: `GraphLoadingNode`
21+
/// - SeeAlso: ``GraphLoadingNode``
2222
public enum DependencyResolutionNode {
2323

2424
/// An empty package node.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2014-2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import enum PackageModel.ProductFilter
14+
import struct PackageModel.PackageReference
15+
16+
public struct DependencyResolverBinding {
17+
public let package: PackageReference
18+
public let boundVersion: BoundVersion
19+
public let products: ProductFilter
20+
}

Sources/PackageGraph/DependencyResolver.swift renamed to Sources/PackageGraph/Resolution/DependencyResolverDelegate.swift

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift open source project
44
//
5-
// Copyright (c) 2014-2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014-2023 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See http://swift.org/LICENSE.txt for license information
@@ -16,25 +16,6 @@ import PackageModel
1616

1717
import struct TSCUtility.Version
1818

19-
public protocol DependencyResolver {
20-
typealias Binding = (package: PackageReference, binding: BoundVersion, products: ProductFilter)
21-
typealias Delegate = DependencyResolverDelegate
22-
}
23-
24-
public enum DependencyResolverError: Error, Equatable {
25-
/// A revision-based dependency contains a local package dependency.
26-
case revisionDependencyContainsLocalPackage(dependency: String, localPackage: String)
27-
}
28-
29-
extension DependencyResolverError: CustomStringConvertible {
30-
public var description: String {
31-
switch self {
32-
case .revisionDependencyContainsLocalPackage(let dependency, let localPackage):
33-
return "package '\(dependency)' is required using a revision-based requirement and it depends on local package '\(localPackage)', which is not supported"
34-
}
35-
}
36-
}
37-
3819
public protocol DependencyResolverDelegate {
3920
func willResolve(term: Term)
4021
func didResolve(term: Term, version: Version, duration: DispatchTimeInterval)
@@ -44,7 +25,7 @@ public protocol DependencyResolverDelegate {
4425
func satisfied(term: Term, by assignment: Assignment, incompatibility: Incompatibility)
4526
func partiallySatisfied(term: Term, by assignment: Assignment, incompatibility: Incompatibility, difference: Term)
4627
func failedToResolve(incompatibility: Incompatibility)
47-
func solved(result: [DependencyResolver.Binding])
28+
func solved(result: [DependencyResolverBinding])
4829
}
4930

5031
public struct ObservabilityDependencyResolverDelegate: DependencyResolverDelegate {
@@ -82,9 +63,9 @@ public struct ObservabilityDependencyResolverDelegate: DependencyResolverDelegat
8263
self.debug("\(term) is partially satisfied by '\(assignment)', which is caused by '\(assignment.cause?.description ?? "unknown cause")'. new incompatibility \(incompatibility)")
8364
}
8465

85-
public func solved(result: [DependencyResolver.Binding]) {
86-
for (package, binding, _) in result {
87-
self.debug("solved '\(package.identity)' (\(package.locationString)) at '\(binding)'")
66+
public func solved(result: [DependencyResolverBinding]) {
67+
for binding in result {
68+
self.debug("solved '\(binding.package.identity)' (\(binding.package.locationString)) at '\(binding.boundVersion)'")
8869
}
8970
self.debug("dependency resolution complete!")
9071
}
@@ -129,7 +110,7 @@ public struct MultiplexResolverDelegate: DependencyResolverDelegate {
129110
underlying.forEach { $0.failedToResolve(incompatibility: incompatibility) }
130111
}
131112

132-
public func solved(result: [(package: PackageReference, binding: BoundVersion, products: ProductFilter)]) {
113+
public func solved(result: [DependencyResolverBinding]) {
133114
underlying.forEach { $0.solved(result: result) }
134115
}
135116

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2014-2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
15+
public enum DependencyResolverError: Error, Equatable {
16+
/// A revision-based dependency contains a local package dependency.
17+
case revisionDependencyContainsLocalPackage(dependency: String, localPackage: String)
18+
}
19+
20+
extension DependencyResolverError: CustomStringConvertible {
21+
public var description: String {
22+
switch self {
23+
case .revisionDependencyContainsLocalPackage(let dependency, let localPackage):
24+
return "package '\(dependency)' is required using a revision-based requirement and it depends on local package '\(localPackage)', which is not supported"
25+
}
26+
}
27+
}

Sources/PackageGraph/PubGrub/PubGrubDependencyResolver.swift renamed to Sources/PackageGraph/Resolution/PubGrub/PubGrubDependencyResolver.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public struct PubGrubDependencyResolver {
140140
}
141141

142142
/// Execute the resolution algorithm to find a valid assignment of versions.
143-
public func solve(constraints: [Constraint]) -> Result<[DependencyResolver.Binding], Error> {
143+
public func solve(constraints: [Constraint]) -> Result<[DependencyResolverBinding], Error> {
144144
// the graph resolution root
145145
let root: DependencyResolutionNode
146146
if constraints.count == 1, let constraint = constraints.first, constraint.package.kind.isRoot {
@@ -180,7 +180,7 @@ public struct PubGrubDependencyResolver {
180180
/// Find a set of dependencies that fit the given constraints. If dependency
181181
/// resolution is unable to provide a result, an error is thrown.
182182
/// - Warning: It is expected that the root package reference has been set before this is called.
183-
internal func solve(root: DependencyResolutionNode, constraints: [Constraint]) throws -> (bindings: [DependencyResolver.Binding], state: State) {
183+
internal func solve(root: DependencyResolutionNode, constraints: [Constraint]) throws -> (bindings: [DependencyResolverBinding], state: State) {
184184
// first process inputs
185185
let inputs = try self.processInputs(root: root, with: constraints)
186186

@@ -241,18 +241,22 @@ public struct PubGrubDependencyResolver {
241241
flattenedAssignments[updatePackage] = (binding: boundVersion, products: products)
242242
}
243243
}
244-
var finalAssignments: [DependencyResolver.Binding]
244+
var finalAssignments: [DependencyResolverBinding]
245245
= flattenedAssignments.keys.sorted(by: { $0.deprecatedName < $1.deprecatedName }).map { package in
246246
let details = flattenedAssignments[package]!
247-
return (package: package, binding: details.binding, products: details.products)
247+
return .init(package: package, boundVersion: details.binding, products: details.products)
248248
}
249249

250250
// Add overridden packages to the result.
251251
for (package, override) in state.overriddenPackages {
252252
// TODO: replace with async/await when available
253253
let container = try temp_await { provider.getContainer(for: package, completion: $0) }
254254
let updatePackage = try container.underlying.loadPackageReference(at: override.version)
255-
finalAssignments.append((updatePackage, override.version, override.products))
255+
finalAssignments.append(.init(
256+
package: updatePackage,
257+
boundVersion: override.version,
258+
products: override.products
259+
))
256260
}
257261

258262
self.delegate?.solved(result: finalAssignments)

Sources/Workspace/Workspace+Dependencies.swift

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import struct PackageGraph.Assignment
2525
import enum PackageGraph.BoundVersion
2626
import enum PackageGraph.ContainerUpdateStrategy
2727
import protocol PackageGraph.CustomPackageContainer
28+
import struct PackageGraph.DependencyResolverBinding
2829
import protocol PackageGraph.DependencyResolverDelegate
2930
import struct PackageGraph.Incompatibility
3031
import struct PackageGraph.MultiplexResolverDelegate
@@ -631,7 +632,7 @@ extension Workspace {
631632
@discardableResult
632633
fileprivate func updateDependenciesCheckouts(
633634
root: PackageGraphRoot,
634-
updateResults: [(PackageReference, BoundVersion, ProductFilter)],
635+
updateResults: [DependencyResolverBinding],
635636
updateBranches: Bool = false,
636637
observabilityScope: ObservabilityScope
637638
) -> [(PackageReference, PackageStateChange)] {
@@ -954,7 +955,7 @@ extension Workspace {
954955
/// Computes states of the packages based on last stored state.
955956
fileprivate func computePackageStateChanges(
956957
root: PackageGraphRoot,
957-
resolvedDependencies: [(PackageReference, BoundVersion, ProductFilter)],
958+
resolvedDependencies: [DependencyResolverBinding],
958959
updateBranches: Bool,
959960
observabilityScope: ObservabilityScope
960961
) throws -> [(PackageReference, PackageStateChange)] {
@@ -963,59 +964,59 @@ extension Workspace {
963964
var packageStateChanges: [PackageIdentity: (PackageReference, PackageStateChange)] = [:]
964965

965966
// Set the states from resolved dependencies results.
966-
for (packageRef, binding, products) in resolvedDependencies {
967+
for binding in resolvedDependencies {
967968
// Get the existing managed dependency for this package ref, if any.
968969

969970
// first find by identity only since edit location may be different by design
970-
var currentDependency = self.state.dependencies[packageRef.identity]
971+
var currentDependency = self.state.dependencies[binding.package.identity]
971972
// Check if this is an edited dependency.
972973
if case .edited(let basedOn, _) = currentDependency?.state, let originalReference = basedOn?.packageRef {
973974
packageStateChanges[originalReference.identity] = (originalReference, .unchanged)
974975
} else {
975976
// if not edited, also compare by location since it may have changed
976-
currentDependency = self.state.dependencies[comparingLocation: packageRef]
977+
currentDependency = self.state.dependencies[comparingLocation: binding.package]
977978
}
978979

979-
switch binding {
980+
switch binding.boundVersion {
980981
case .excluded:
981982
throw InternalError("Unexpected excluded binding")
982983

983984
case .unversioned:
984985
// Ignore the root packages.
985-
if root.packages.keys.contains(packageRef.identity) {
986+
if root.packages.keys.contains(binding.package.identity) {
986987
continue
987988
}
988989

989990
if let currentDependency {
990991
switch currentDependency.state {
991992
case .fileSystem, .edited:
992-
packageStateChanges[packageRef.identity] = (packageRef, .unchanged)
993+
packageStateChanges[binding.package.identity] = (binding.package, .unchanged)
993994
case .sourceControlCheckout:
994-
let newState = PackageStateChange.State(requirement: .unversioned, products: products)
995-
packageStateChanges[packageRef.identity] = (packageRef, .updated(newState))
995+
let newState = PackageStateChange.State(requirement: .unversioned, products: binding.products)
996+
packageStateChanges[binding.package.identity] = (binding.package, .updated(newState))
996997
case .registryDownload:
997998
throw InternalError("Unexpected unversioned binding for downloaded dependency")
998999
case .custom:
9991000
throw InternalError("Unexpected unversioned binding for custom dependency")
10001001
}
10011002
} else {
1002-
let newState = PackageStateChange.State(requirement: .unversioned, products: products)
1003-
packageStateChanges[packageRef.identity] = (packageRef, .added(newState))
1003+
let newState = PackageStateChange.State(requirement: .unversioned, products: binding.products)
1004+
packageStateChanges[binding.package.identity] = (binding.package, .added(newState))
10041005
}
10051006

10061007
case .revision(let identifier, let branch):
10071008
// Get the latest revision from the container.
10081009
// TODO: replace with async/await when available
10091010
guard let container = try (temp_await {
10101011
packageContainerProvider.getContainer(
1011-
for: packageRef,
1012+
for: binding.package,
10121013
updateStrategy: .never,
10131014
observabilityScope: observabilityScope,
10141015
on: .sharedConcurrent,
10151016
completion: $0
10161017
)
10171018
}) as? SourceControlPackageContainer else {
1018-
throw InternalError("invalid container for \(packageRef) expected a SourceControlPackageContainer")
1019+
throw InternalError("invalid container for \(binding.package) expected a SourceControlPackageContainer")
10191020
}
10201021
var revision = try container.getRevision(forIdentifier: identifier)
10211022
let branch = branch ?? (identifier == revision.identifier ? nil : identifier)
@@ -1024,7 +1025,7 @@ extension Workspace {
10241025
// branches, use the revision from pin instead (if present).
10251026
if branch != nil, !updateBranches {
10261027
if case .branch(branch, let pinRevision) = pinsStore.pins.values
1027-
.first(where: { $0.packageRef == packageRef })?.state
1028+
.first(where: { $0.packageRef == binding.package })?.state
10281029
{
10291030
revision = Revision(identifier: pinRevision)
10301031
}
@@ -1043,21 +1044,21 @@ extension Workspace {
10431044
if case .sourceControlCheckout(let checkoutState) = currentDependency.state,
10441045
checkoutState == newState
10451046
{
1046-
packageStateChanges[packageRef.identity] = (packageRef, .unchanged)
1047+
packageStateChanges[binding.package.identity] = (binding.package, .unchanged)
10471048
} else {
10481049
// Otherwise, we need to update this dependency to this revision.
10491050
let newState = PackageStateChange.State(
10501051
requirement: .revision(revision, branch: branch),
1051-
products: products
1052+
products: binding.products
10521053
)
1053-
packageStateChanges[packageRef.identity] = (packageRef, .updated(newState))
1054+
packageStateChanges[binding.package.identity] = (binding.package, .updated(newState))
10541055
}
10551056
} else {
10561057
let newState = PackageStateChange.State(
10571058
requirement: .revision(revision, branch: branch),
1058-
products: products
1059+
products: binding.products
10591060
)
1060-
packageStateChanges[packageRef.identity] = (packageRef, .added(newState))
1061+
packageStateChanges[binding.package.identity] = (binding.package, .added(newState))
10611062
}
10621063

10631064
case .version(let version):
@@ -1066,11 +1067,11 @@ extension Workspace {
10661067
case .sourceControlCheckout(.version(version, _)), .registryDownload(version), .custom(version, _):
10671068
stateChange = .unchanged
10681069
case .edited, .fileSystem, .sourceControlCheckout, .registryDownload, .custom:
1069-
stateChange = .updated(.init(requirement: .version(version), products: products))
1070+
stateChange = .updated(.init(requirement: .version(version), products: binding.products))
10701071
case nil:
1071-
stateChange = .added(.init(requirement: .version(version), products: products))
1072+
stateChange = .added(.init(requirement: .version(version), products: binding.products))
10721073
}
1073-
packageStateChanges[packageRef.identity] = (packageRef, stateChange)
1074+
packageStateChanges[binding.package.identity] = (binding.package, stateChange)
10741075
}
10751076
}
10761077
// Set the state of any old package that might have been removed.
@@ -1114,7 +1115,7 @@ extension Workspace {
11141115
resolver: PubGrubDependencyResolver,
11151116
constraints: [PackageContainerConstraint],
11161117
observabilityScope: ObservabilityScope
1117-
) -> [(package: PackageReference, binding: BoundVersion, products: ProductFilter)] {
1118+
) -> [DependencyResolverBinding] {
11181119
os_signpost(.begin, name: SignpostName.pubgrub)
11191120
let result = resolver.solve(constraints: constraints)
11201121
os_signpost(.end, name: SignpostName.pubgrub)
@@ -1179,7 +1180,7 @@ private struct WorkspaceDependencyResolverDelegate: DependencyResolverDelegate {
11791180
difference: Term
11801181
) {}
11811182
func failedToResolve(incompatibility: Incompatibility) {}
1182-
func solved(result: [(package: PackageReference, binding: BoundVersion, products: ProductFilter)]) {}
1183+
func solved(result: [DependencyResolverBinding]) {}
11831184
}
11841185

11851186
// FIXME: the manifest loading logic should be changed to use identity instead of location once identity is unique

Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class DependencyResolverRealWorldPerfTests: XCTestCasePerf {
6969
switch resolver.solve(constraints: graph.constraints) {
7070
case .success(let result):
7171
let result: [(container: PackageReference, version: Version)] = result.compactMap {
72-
guard case .version(let version) = $0.binding else {
72+
guard case .version(let version) = $0.boundVersion else {
7373
XCTFail("Unexpected result")
7474
return nil
7575
}

0 commit comments

Comments
 (0)