Skip to content
280 changes: 124 additions & 156 deletions Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphLoader.swift

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
Copyright (c) 2021-2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -131,28 +131,30 @@ public struct DefaultAvailability: Codable, Equatable {

/// Fallback availability information for platforms we either don't emit SGFs for
/// or have the same availability information as another platform.
package static let fallbackPlatforms: [PlatformName: PlatformName] = [
.catalyst: .iOS,
.iPadOS: .iOS,
]
///
/// The key corresponds to the fallback platform and the value to the platform it's
/// fallbacking from.
package static let fallbackPlatforms: [PlatformName: [PlatformName]] = [.iOS: [.catalyst, .iPadOS]]

/// Creates a default availability module.
/// - Parameter modules: A map of modules and the default platform availability for symbols in that module.
public init(with modules: [String: [ModuleAvailability]]) {
self.modules = modules.mapValues { platformAvailabilities -> [DefaultAvailability.ModuleAvailability] in
// If a module doesn't contain default availability information for any of the fallback platforms,
// infer it from the corresponding mapped value.
platformAvailabilities + DefaultAvailability.fallbackPlatforms.compactMap { (platform, fallbackPlatform) in
if !platformAvailabilities.contains(where: { $0.platformName == platform }),
let fallbackAvailability = platformAvailabilities.first(where: { $0.platformName == fallbackPlatform }),
let fallbackIntroducedVersion = fallbackAvailability.introducedVersion
{
return DefaultAvailability.ModuleAvailability(
platformName: platform,
platformVersion: fallbackIntroducedVersion
)
platformAvailabilities + DefaultAvailability.fallbackPlatforms.flatMap { (fallbackPlatform, platform) in
platform.compactMap { platformName in
if !platformAvailabilities.contains(where: { $0.platformName == platformName }),
let fallbackAvailability = platformAvailabilities.first(where: { $0.platformName == fallbackPlatform }),
let fallbackIntroducedVersion = fallbackAvailability.introducedVersion
{
return DefaultAvailability.ModuleAvailability(
platformName: platformName,
platformVersion: fallbackIntroducedVersion
)
}
return nil
}
return nil
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions Sources/SwiftDocC/Semantics/Symbol/Symbol.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
Copyright (c) 2021-2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -591,10 +591,12 @@ extension Symbol {
func mergeAvailabilities(unifiedSymbol: UnifiedSymbolGraph.Symbol) {
for (selector, mixins) in unifiedSymbol.mixins {
let trait = DocumentationDataVariantsTrait(for: selector)
if let unifiedSymbolAvailability = mixins[SymbolGraph.Symbol.Availability.mixinKey] as? SymbolGraph.Symbol.Availability {
guard let availabilityVariantTrait = availabilityVariants[trait] else {
return
}
if let unifiedSymbolAvailability = mixins.getValueIfPresent(for: SymbolGraph.Symbol.Availability.self) {
unifiedSymbolAvailability.availability.forEach { availabilityItem in
guard let availabilityVariantTrait = availabilityVariants[trait] else { return }
if (availabilityVariantTrait.availability.contains(where: { $0.domain?.rawValue == availabilityItem.domain?.rawValue })) {
guard availabilityVariantTrait.availability.firstIndex(where: { $0.domain?.rawValue == availabilityItem.domain?.rawValue }) == nil else {
return
}
availabilityVariants[trait]?.availability.append(availabilityItem)
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftDocCTestUtilities/FilesAndFolders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public struct InfoPlist: File, DataRepresentable {
self.identifier = identifier
self.defaultAvailability = defaultAvailability
}

public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: DocumentationBundle.Info.CodingKeys.self)
displayName = try container.decodeIfPresent(String.self, forKey: .displayName)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
Copyright (c) 2021-2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -145,8 +145,10 @@ public struct ConvertAction: AsyncAction {
// Inject current platform versions if provided
if var currentPlatforms {
// Add missing platforms if their fallback platform is present.
for (platform, fallbackPlatform) in DefaultAvailability.fallbackPlatforms where currentPlatforms[platform.displayName] == nil {
currentPlatforms[platform.displayName] = currentPlatforms[fallbackPlatform.displayName]
for (fallbackPlatform, platforms) in DefaultAvailability.fallbackPlatforms {
for platform in platforms where currentPlatforms[platform.displayName] == nil {
currentPlatforms[platform.displayName] = currentPlatforms[fallbackPlatform.displayName]
}
}
configuration.externalMetadata.currentPlatforms = currentPlatforms
}
Expand Down
Loading