Skip to content

Commit 1c917e0

Browse files
authored
Diagnose invalid module alias (#6841)
Declaring a module alias for a target that isn't a recursive dependency of the product the alias is being defined for doesn't actually work, instead it gets silently skipped. This adds a diagnostic for this case. I don't know if this scenario should work, but it doesn't in practice, so even if it is supposed to, a diagnostic seems better than nothing. Separately, it seems problematic that the duplicateModule diagnostic contains a completely context-free suggestion to use module aliases. This leads to the very confusing outcome that it is being suggested in this particular case which cannot be resolved using a module alias. rdar://114200576
1 parent 52ad263 commit 1c917e0

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

Sources/PackageGraph/ModuleAliasTracker.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ModuleAliasTracker {
2424
var parentToChildProducts = [String: [String]]()
2525
var parentToChildIDs = [PackageIdentity: [PackageIdentity]]()
2626
var childToParentID = [PackageIdentity: PackageIdentity]()
27+
var appliedAliases = Set<String>()
2728

2829
init() {}
2930
func addTargetAliases(targets: [Target], package: PackageIdentity) throws {
@@ -63,7 +64,7 @@ class ModuleAliasTracker {
6364
}
6465

6566
for (originalName, newName) in aliases {
66-
let model = ModuleAliasModel(name: originalName, alias: newName, originPackage: originPackage, consumingPackage: consumingPackage)
67+
let model = ModuleAliasModel(name: originalName, alias: newName, originPackage: originPackage, consumingPackage: consumingPackage, productName: productName)
6768
idToAliasMap[originPackage, default: [:]][productID, default: []].append(model)
6869
aliasMap[productID, default: []].append(model)
6970
}
@@ -163,13 +164,22 @@ class ModuleAliasTracker {
163164

164165
for relTarget in relevantTargets {
165166
if let val = lookupAlias(key: relTarget.name, in: aliasBuffer) {
167+
appliedAliases.insert(relTarget.name)
166168
relTarget.addModuleAlias(for: relTarget.name, as: val)
167169
if let prechainVal = aliasBuffer[relTarget.name],
168170
prechainVal.alias != val {
169171
relTarget.addPrechainModuleAlias(for: relTarget.name, as: prechainVal.alias)
172+
appliedAliases.insert(prechainVal.alias)
170173
relTarget.addPrechainModuleAlias(for: prechainVal.alias, as: val)
171174
observabilityScope.emit(info: "Module alias '\(prechainVal.alias)' defined in package '\(prechainVal.consumingPackage)' for target '\(relTarget.name)' in package/product '\(productID)' is overridden by alias '\(val)'; if this override is not intended, remove '\(val)' from 'moduleAliases' in its manifest")
172175
aliasBuffer.removeValue(forKey: prechainVal.alias)
176+
177+
// Since we're overriding an alias here, we have to pretend it was applied to avoid follow-on warnings.
178+
var currentAlias: String? = val
179+
while let _currentAlias = currentAlias, !appliedAliases.contains(_currentAlias) {
180+
appliedAliases.insert(_currentAlias)
181+
currentAlias = aliasBuffer.values.first { $0.alias == _currentAlias }?.name
182+
}
173183
}
174184
aliasBuffer.removeValue(forKey: relTarget.name)
175185
}
@@ -257,6 +267,7 @@ class ModuleAliasTracker {
257267
for target in productTargets {
258268
let depAliases = target.recursiveDependentTargets.compactMap{$0.moduleAliases}.flatMap{$0}
259269
for (key, alias) in depAliases {
270+
appliedAliases.insert(key)
260271
target.addModuleAlias(for: key, as: alias)
261272
}
262273
}
@@ -269,6 +280,16 @@ class ModuleAliasTracker {
269280
}
270281
}
271282

283+
func diagnoseUnappliedAliases(observabilityScope: ObservabilityScope) {
284+
for aliasList in aliasMap.values {
285+
for productAlias in aliasList {
286+
if !appliedAliases.contains(productAlias.name) {
287+
observabilityScope.emit(warning: "module alias for target '\(productAlias.name)', declared in package '\(productAlias.consumingPackage)', does not match any recursive target dependency of product '\(productAlias.productName)' from package '\(productAlias.originPackage)'")
288+
}
289+
}
290+
}
291+
}
292+
272293
private func chainModuleAliases(targets: [Target],
273294
checkedTargets: [Target],
274295
targetAliases: [String: [String]],
@@ -336,11 +357,13 @@ class ModuleAliasTracker {
336357

337358
for target in targets {
338359
for (key, val) in aliasDict {
360+
appliedAliases.insert(key)
339361
target.addModuleAlias(for: key, as: val)
340362
}
341363
for (key, valList) in prechainAliasDict {
342364
if let val = valList.first,
343365
valList.count <= 1 {
366+
appliedAliases.insert(key)
344367
target.addModuleAlias(for: key, as: val)
345368
target.addPrechainModuleAlias(for: key, as: val)
346369
}
@@ -401,12 +424,14 @@ class ModuleAliasModel {
401424
var alias: String
402425
let originPackage: PackageIdentity
403426
let consumingPackage: PackageIdentity
427+
let productName: String
404428

405-
init(name: String, alias: String, originPackage: PackageIdentity, consumingPackage: PackageIdentity) {
429+
init(name: String, alias: String, originPackage: PackageIdentity, consumingPackage: PackageIdentity, productName: String) {
406430
self.name = name
407431
self.alias = alias
408432
self.originPackage = originPackage
409433
self.consumingPackage = consumingPackage
434+
self.productName = productName
410435
}
411436
}
412437

Sources/PackageGraph/PackageGraph+Loading.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,10 @@ private func resolveModuleAliases(packageBuilders: [ResolvedPackageBuilder],
799799
observabilityScope: observabilityScope)
800800
}
801801
}
802+
803+
// Emit diagnostics for any module aliases that did not end up being applied.
804+
aliasTracker.diagnoseUnappliedAliases(observabilityScope: observabilityScope)
805+
802806
return true
803807
}
804808

0 commit comments

Comments
 (0)