Skip to content

Commit e6d992c

Browse files
committed
Add fix-it when there's a package target with similar name as the one provided in the dependency
1 parent 4eba383 commit e6d992c

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

Sources/PackageGraph/PackageGraph+Loading.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import PackageLoading
1616
import PackageModel
1717

1818
import func TSCBasic.topologicalSort
19+
import func TSCBasic.bestMatch
1920

2021
extension PackageGraph {
2122

@@ -495,13 +496,16 @@ private func createResolvedPackages(
495496
}.map {$0.targets}.flatMap{$0}.filter { t in
496497
t.name != productRef.name
497498
}
498-
499+
500+
// Find and pick the minimun distance between the available products dependencies and provided the product name
501+
let bestMatchedPackageName = bestMatch(for: productRef.name, from: Array(allTargetNames))
499502
let error = PackageGraphError.productDependencyNotFound(
500503
package: package.identity.description,
501504
targetName: targetBuilder.target.name,
502505
dependencyProductName: productRef.name,
503506
dependencyPackageName: productRef.package,
504-
dependencyProductInDecl: !declProductsAsDependency.isEmpty
507+
dependencyProductInDecl: !declProductsAsDependency.isEmpty,
508+
similarPackageName: bestMatchedPackageName
505509
)
506510
packageObservabilityScope.emit(error)
507511
}

Sources/PackageGraph/PackageGraph.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ enum PackageGraphError: Swift.Error {
2323
case cycleDetected((path: [Manifest], cycle: [Manifest]))
2424

2525
/// The product dependency not found.
26-
case productDependencyNotFound(package: String, targetName: String, dependencyProductName: String, dependencyPackageName: String?, dependencyProductInDecl: Bool)
26+
case productDependencyNotFound(package: String, targetName: String, dependencyProductName: String, dependencyPackageName: String?, dependencyProductInDecl: Bool, similarPackageName: String?)
2727

2828
/// The package dependency already satisfied by a different dependency package
2929
case dependencyAlreadySatisfiedByIdentifier(package: String, dependencyLocation: String, otherDependencyURL: String, identity: PackageIdentity)
@@ -219,11 +219,15 @@ extension PackageGraphError: CustomStringConvertible {
219219
(cycle.path + cycle.cycle).map({ $0.displayName }).joined(separator: " -> ") +
220220
" -> " + cycle.cycle[0].displayName
221221

222-
case .productDependencyNotFound(let package, let targetName, let dependencyProductName, let dependencyPackageName, let dependencyProductInDecl):
222+
case .productDependencyNotFound(let package, let targetName, let dependencyProductName, let dependencyPackageName, let dependencyProductInDecl, let similarPackageName):
223223
if dependencyProductInDecl {
224224
return "product '\(dependencyProductName)' is declared in the same package '\(package)' and can't be used as a dependency for target '\(targetName)'."
225225
} else {
226-
return "product '\(dependencyProductName)' required by package '\(package)' target '\(targetName)' \(dependencyPackageName.map{ "not found in package '\($0)'" } ?? "not found")."
226+
var description = "product '\(dependencyProductName)' required by package '\(package)' target '\(targetName)' \(dependencyPackageName.map{ "not found in package '\($0)'" } ?? "not found")."
227+
if let similarPackageName {
228+
description += " did you mean '\(similarPackageName)'?"
229+
}
230+
return description
227231
}
228232
case .dependencyAlreadySatisfiedByIdentifier(let package, let dependencyURL, let otherDependencyURL, let identity):
229233
return "'\(package)' dependency on '\(dependencyURL)' conflicts with dependency on '\(otherDependencyURL)' which has the same identity '\(identity)'"

Tests/PackageGraphTests/PackageGraphTests.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,43 @@ class PackageGraphTests: XCTestCase {
786786
}
787787
}
788788

789+
func testProductDependencyWithSimilarName() throws {
790+
let fs = InMemoryFileSystem(emptyFiles:
791+
"/Foo/Sources/FooTarget/foo.swift",
792+
"/Bar/Sources/BarTarget/bar.swift"
793+
)
794+
795+
let observability = ObservabilitySystem.makeForTesting()
796+
_ = try loadPackageGraph(
797+
fileSystem: fs,
798+
manifests: [
799+
Manifest.createRootManifest(
800+
displayName: "Foo",
801+
path: "/Foo",
802+
targets: [
803+
TargetDescription(name: "FooTarget", dependencies: ["Barx"]),
804+
]),
805+
Manifest.createRootManifest(
806+
displayName: "Bar",
807+
path: "/Bar",
808+
products: [
809+
ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"])
810+
],
811+
targets: [
812+
TargetDescription(name: "BarTarget")
813+
]),
814+
],
815+
observabilityScope: observability.topScope
816+
)
817+
818+
testDiagnostics(observability.diagnostics) { result in
819+
result.check(
820+
diagnostic: "product 'Barx' required by package 'foo' target 'FooTarget' not found. did you mean 'Bar'?",
821+
severity: .error
822+
)
823+
}
824+
}
825+
789826
func testProductDependencyDeclaredInSamePackage() throws {
790827
let fs = InMemoryFileSystem(emptyFiles:
791828
"/Foo/Sources/FooTarget/src.swift",

0 commit comments

Comments
 (0)