Skip to content

Fix availability logic refactor #1065

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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