Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -187,6 +187,26 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator {
return declarations
}

/// Returns the given platforms with any missing fallback platforms added.
///
/// This function uses the centralized `DefaultAvailability.fallbackPlatforms` mapping to ensure
/// consistency with platform expansion logic used throughout the codebase.
///
/// For example, when iOS is present in the platforms array, this function adds iPadOS and Mac Catalyst
/// if they are not already included.
///
/// - Parameter platforms: The original platforms array.
/// - Returns: The platforms array with fallback platforms added where applicable.
func expandPlatformsWithFallbacks(_ platforms: [PlatformName?]) -> [PlatformName?] {
guard !platforms.isEmpty else { return platforms }

// Add fallback platforms if their primary platform is present but the fallback is missing
let fallbacks = DefaultAvailability.fallbackPlatforms.compactMap { fallback, primary in
platforms.contains(primary) && !platforms.contains(fallback) ? fallback : nil
}
return platforms + fallbacks
}

func comparePlatformNames(_ lhs: PlatformName?, _ rhs: PlatformName?) -> Bool {
guard let lhsValue = lhs, let rhsValue = rhs else {
return lhs == nil
Expand All @@ -204,6 +224,8 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator {
]
for pair in declaration {
let (platforms, declaration) = pair
let expandedPlatforms = expandPlatformsWithFallbacks(platforms)
let platformNames = sortPlatformNames(expandedPlatforms)

let renderedTokens: [DeclarationRenderSection.Token]
let otherDeclarations: DeclarationRenderSection.OtherDeclarations?
Expand Down Expand Up @@ -242,7 +264,7 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator {
declarations.append(
DeclarationRenderSection(
languages: languages,
platforms: sortPlatformNames(platforms),
platforms: platformNames,
tokens: renderedTokens,
otherDeclarations: otherDeclarations
)
Expand All @@ -252,7 +274,8 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator {
if let alternateDeclarations = symbol.alternateDeclarationVariants[trait] {
for pair in alternateDeclarations {
let (platforms, decls) = pair
let platformNames = sortPlatformNames(platforms)
let expandedPlatforms = expandPlatformsWithFallbacks(platforms)
let platformNames = sortPlatformNames(expandedPlatforms)
for alternateDeclaration in decls {
let renderedTokens = alternateDeclaration.declarationFragments.map(translateFragment)

Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ class SemaToRenderNodeTests: XCTestCase {
return
}

XCTAssertEqual(declarations.declarations[0].platforms, [PlatformName(operatingSystemName: "ios")])
XCTAssertEqual(Set(declarations.declarations[0].platforms), Set([PlatformName(operatingSystemName: "ios"), PlatformName.iPadOS, PlatformName.catalyst]))
XCTAssertEqual(declarations.declarations[0].tokens.count, 5)
XCTAssertEqual(declarations.declarations[0].tokens.map { $0.text }.joined(), "protocol MyProtocol : Hashable")
XCTAssertEqual(declarations.declarations[0].languages?.first, "swift")
Expand Down Expand Up @@ -1257,7 +1257,7 @@ class SemaToRenderNodeTests: XCTestCase {
return
}

XCTAssertEqual(declarations.declarations[0].platforms, [PlatformName(operatingSystemName: "ios")])
XCTAssertEqual(Set(declarations.declarations[0].platforms), Set([PlatformName(operatingSystemName: "ios"), PlatformName.iPadOS, PlatformName.catalyst]))
XCTAssertEqual(declarations.declarations[0].tokens.count, 5)
XCTAssertEqual(declarations.declarations[0].tokens.map { $0.text }.joined(), "protocol MyProtocol : Hashable")
XCTAssertEqual(declarations.declarations[0].languages?.first, "swift")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class DeclarationsRenderSectionTests: XCTestCase {
let declarationsSection = try XCTUnwrap(renderNode.primaryContentSections.compactMap({ $0 as? DeclarationsRenderSection }).first)

XCTAssertEqual(declarationsSection.declarations.count, 2)
XCTAssert(declarationsSection.declarations.allSatisfy({ $0.platforms == [.iOS, .macOS] }))
XCTAssert(declarationsSection.declarations.allSatisfy({ Set($0.platforms) == Set([.iOS, .iPadOS, .macOS, .catalyst]) }))
}

func testPlatformSpecificDeclarations() async throws {
Expand Down Expand Up @@ -223,7 +223,7 @@ class DeclarationsRenderSectionTests: XCTestCase {
let declarationsSection = try XCTUnwrap(renderNode.primaryContentSections.compactMap({ $0 as? DeclarationsRenderSection }).first)
XCTAssertEqual(declarationsSection.declarations.count, 2)

XCTAssertEqual(declarationsSection.declarations[0].platforms, [.iOS])
XCTAssertEqual(Set(declarationsSection.declarations[0].platforms), Set([.iOS, .iPadOS, .catalyst]))
XCTAssertEqual(declarationsSection.declarations[0].tokens.map(\.text).joined(),
"init(_ content: OtherClass) throws")
XCTAssertEqual(declarationsSection.declarations[1].platforms, [.macOS])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ class RenderNodeTranslatorSymbolVariantsTests: XCTestCase {
},
assertAfterApplyingVariant: { renderNode in
let declarationSection = try declarationSection(in: renderNode)
XCTAssertEqual(declarationSection.platforms, [.iOS])
XCTAssertEqual(Set(declarationSection.platforms), Set([.iOS, .iPadOS, .catalyst]))

XCTAssertEqual(
declarationSection.tokens,
Expand Down