@@ -505,7 +505,7 @@ private func createResolvedPackages(
505
505
throw InternalError ( " dependency reference for \( product. packageBuilder. package . manifest. packageLocation) not found " )
506
506
}
507
507
let referencedPackageName = referencedPackageDependency. nameForTargetDependencyResolutionOnly
508
- if productRef. name != referencedPackageName {
508
+ if productRef. name != referencedPackageName {
509
509
let error = PackageGraphError . productDependencyMissingPackage (
510
510
productName: productRef. name,
511
511
targetName: targetBuilder. target. name,
@@ -522,16 +522,84 @@ private func createResolvedPackages(
522
522
523
523
// If a target with similar name was encountered before, we emit a diagnostic.
524
524
if foundDuplicateTarget {
525
+ var duplicateTargets = [ String: [ Package] ] ( )
525
526
for targetName in allTargetNames. sorted ( ) {
526
- // Find the packages this target is present in.
527
527
let packages = packageBuilders
528
528
. filter ( { $0. targets. contains ( where: { $0. target. name == targetName } ) } )
529
- . map { $0. package . identity. description }
530
- . sorted ( )
529
+ . map { $0. package }
531
530
if packages. count > 1 {
532
- observabilityScope . emit ( ModuleError . duplicateModule ( targetName, packages) )
531
+ duplicateTargets [ targetName, default : [ ] ] . append ( contentsOf : packages)
533
532
}
534
533
}
534
+
535
+ struct Pair : Hashable {
536
+ let package1 : Package
537
+ let package2 : Package
538
+
539
+ static func == ( lhs: Pair , rhs: Pair ) -> Bool {
540
+ return lhs. package1. identity == rhs. package1. identity &&
541
+ lhs. package2. identity == rhs. package2. identity
542
+ }
543
+
544
+ public func hash( into hasher: inout Hasher ) {
545
+ hasher. combine ( self . package1. identity)
546
+ hasher. combine ( self . package2. identity)
547
+ }
548
+ }
549
+
550
+ var potentiallyDuplicatePackages = [ Pair: [ String] ] ( )
551
+ for entry in duplicateTargets {
552
+ // the duplicate is across exactly two packages
553
+ if entry. value. count == 2 {
554
+ potentiallyDuplicatePackages [ Pair ( package1: entry. value [ 0 ] , package2: entry. value [ 1 ] ) , default: [ ] ] . append ( entry. key)
555
+ }
556
+ }
557
+
558
+ var duplicateTargetsAddressed = [ String] ( )
559
+ for potentiallyDuplicatePackage in potentiallyDuplicatePackages {
560
+ // more than three target matches, or all targets in the package match
561
+ if potentiallyDuplicatePackage. value. count > 3 ||
562
+ ( potentiallyDuplicatePackage. value. sorted ( ) == potentiallyDuplicatePackage. key. package1. targets. map ( { $0. name } ) . sorted ( )
563
+ &&
564
+ potentiallyDuplicatePackage. value. sorted ( ) == potentiallyDuplicatePackage. key. package2. targets. map ( { $0. name } ) . sorted ( ) )
565
+ {
566
+ switch ( potentiallyDuplicatePackage. key. package1. identity. registry, potentiallyDuplicatePackage. key. package2. identity. registry) {
567
+ case ( . some( let registryIdentity) , . none) :
568
+ observabilityScope. emit (
569
+ ModuleError . duplicateModulesScmAndRegistry (
570
+ regsitryPackage: registryIdentity,
571
+ scmPackage: potentiallyDuplicatePackage. key. package2. identity,
572
+ targets: potentiallyDuplicatePackage. value
573
+ )
574
+ )
575
+ case ( . none, . some( let registryIdentity) ) :
576
+ observabilityScope. emit (
577
+ ModuleError . duplicateModulesScmAndRegistry (
578
+ regsitryPackage: registryIdentity,
579
+ scmPackage: potentiallyDuplicatePackage. key. package1. identity,
580
+ targets: potentiallyDuplicatePackage. value
581
+ )
582
+ )
583
+ default :
584
+ observabilityScope. emit (
585
+ ModuleError . duplicateModules (
586
+ package : potentiallyDuplicatePackage. key. package1. identity,
587
+ otherPackage: potentiallyDuplicatePackage. key. package2. identity,
588
+ targets: potentiallyDuplicatePackage. value
589
+ )
590
+ )
591
+ }
592
+ duplicateTargetsAddressed += potentiallyDuplicatePackage. value
593
+ }
594
+ }
595
+
596
+ for entry in duplicateTargets. filter ( { !duplicateTargetsAddressed. contains ( $0. key) } ) {
597
+ observabilityScope. emit (
598
+ ModuleError . duplicateModule (
599
+ targetName: entry. key,
600
+ packages: entry. value. map { $0. identity } )
601
+ )
602
+ }
535
603
}
536
604
537
605
return try packageBuilders. map { try $0. construct ( ) }
0 commit comments