Skip to content

Commit 617867d

Browse files
use SymbolKit's "alternate declarations" in declarations sections (#654)
rdar://70594078
1 parent 7cdca7f commit 617867d

File tree

7 files changed

+460
-20
lines changed

7 files changed

+460
-20
lines changed

Package.resolved

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/SwiftDocC/Model/Rendering/RenderSectionTranslator/DeclarationsSectionTranslator.swift

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
import Foundation
12+
import SymbolKit
1213

1314
/// Translates a symbol's declaration into a render node's Declarations section.
1415
struct DeclarationsSectionTranslator: RenderSectionTranslator {
@@ -23,27 +24,28 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator {
2324
guard !declaration.isEmpty else {
2425
return nil
2526
}
26-
27+
28+
func translateFragment(_ token: SymbolGraph.Symbol.DeclarationFragments.Fragment) -> DeclarationRenderSection.Token {
29+
// Create a reference if one found
30+
var reference: ResolvedTopicReference?
31+
if let preciseIdentifier = token.preciseIdentifier,
32+
let resolved = renderNodeTranslator.context.symbolIndex[preciseIdentifier] {
33+
reference = resolved
34+
35+
// Add relationship to render references
36+
renderNodeTranslator.collectedTopicReferences.append(resolved)
37+
}
38+
39+
// Add the declaration token
40+
return DeclarationRenderSection.Token(fragment: token, identifier: reference?.absoluteString)
41+
}
42+
2743
var declarations = [DeclarationRenderSection]()
2844
for pair in declaration {
2945
let (platforms, declaration) = pair
3046

31-
let renderedTokens = declaration.declarationFragments.map { token -> DeclarationRenderSection.Token in
32-
33-
// Create a reference if one found
34-
var reference: ResolvedTopicReference?
35-
if let preciseIdentifier = token.preciseIdentifier,
36-
let resolved = renderNodeTranslator.context.symbolIndex[preciseIdentifier] {
37-
reference = resolved
38-
39-
// Add relationship to render references
40-
renderNodeTranslator.collectedTopicReferences.append(resolved)
41-
}
42-
43-
// Add the declaration token
44-
return DeclarationRenderSection.Token(fragment: token, identifier: reference?.absoluteString)
45-
}
46-
47+
let renderedTokens = declaration.declarationFragments.map(translateFragment)
48+
4749
let platformNames = platforms.sorted { (lhs, rhs) -> Bool in
4850
guard let lhsValue = lhs, let rhsValue = rhs else {
4951
return lhs == nil
@@ -59,7 +61,28 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator {
5961
)
6062
)
6163
}
62-
64+
65+
if let alternateDeclarations = symbol.alternateDeclarationVariants[trait] {
66+
for pair in alternateDeclarations {
67+
let (platforms, decls) = pair
68+
for alternateDeclaration in decls {
69+
let renderedTokens = alternateDeclaration.declarationFragments.map(translateFragment)
70+
71+
let platformNames = platforms
72+
.compactMap { $0 }
73+
.sorted(by: \.rawValue)
74+
75+
declarations.append(
76+
DeclarationRenderSection(
77+
languages: [trait.interfaceLanguage ?? renderNodeTranslator.identifier.sourceLanguage.id],
78+
platforms: platformNames,
79+
tokens: renderedTokens
80+
)
81+
)
82+
}
83+
}
84+
}
85+
6386
return DeclarationsRenderSection(declarations: declarations)
6487
}
6588
}

Sources/SwiftDocC/Semantics/Symbol/Symbol.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,10 @@ public final class Symbol: Semantic, Abstracted, Redirected, AutomaticTaskGroups
150150
public var declarationVariants = DocumentationDataVariants<[[PlatformName?]: SymbolGraph.Symbol.DeclarationFragments]>(
151151
defaultVariantValue: [:]
152152
)
153-
153+
154+
/// The symbols alternate declarations in each language variant the symbol is available in.
155+
public var alternateDeclarationVariants = DocumentationDataVariants<[[PlatformName?]: [SymbolGraph.Symbol.DeclarationFragments]]>()
156+
154157
public var locationVariants = DocumentationDataVariants<SymbolGraph.Symbol.Location>()
155158

156159
/// The symbol's availability or conformance constraints, in each language variant the symbol is available in.
@@ -307,6 +310,8 @@ public final class Symbol: Semantic, Abstracted, Redirected, AutomaticTaskGroups
307310
self.locationVariants[trait] = location
308311
case let spi as SymbolGraph.Symbol.SPI:
309312
self.isSPIVariants[trait] = spi.isSPI
313+
case let alternateDeclarations as SymbolGraph.Symbol.AlternateDeclarations:
314+
self.alternateDeclarationVariants[trait] = [[platformNameVariants[trait]]: alternateDeclarations.declarations]
310315
default: break;
311316
}
312317
}

Tests/SwiftDocCTests/Rendering/DeclarationsRenderSectionTests.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,25 @@ class DeclarationsRenderSectionTests: XCTestCase {
8080
let value = try JSONDecoder().decode(DeclarationsRenderSection.self, from: jsonData)
8181
try assertRoundTripCoding(value)
8282
}
83+
84+
func testAlternateDeclarations() throws {
85+
let (bundle, context) = try testBundleAndContext(named: "AlternateDeclarations")
86+
let reference = ResolvedTopicReference(
87+
bundleIdentifier: bundle.identifier,
88+
path: "/documentation/AlternateDeclarations/MyClass/present(completion:)",
89+
sourceLanguage: .swift
90+
)
91+
let symbol = try XCTUnwrap(context.entity(with: reference).semantic as? Symbol)
92+
var translator = RenderNodeTranslator(
93+
context: context,
94+
bundle: bundle,
95+
identifier: reference,
96+
source: nil
97+
)
98+
let renderNode = try XCTUnwrap(translator.visitSymbol(symbol) as? RenderNode)
99+
let declarationsSection = try XCTUnwrap(renderNode.primaryContentSections.compactMap({ $0 as? DeclarationsRenderSection }).first)
100+
101+
XCTAssertEqual(declarationsSection.declarations.count, 2)
102+
XCTAssert(declarationsSection.declarations.allSatisfy({ $0.platforms == [.macOS] }))
103+
}
83104
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# ``AlternateDeclarations``
2+
3+
This bundle contains a class translated from Objective-C. That class contains one method, which was
4+
written to accept a completion handler. The Swift translation converted this into two methods: one
5+
with the original completion handler parameter, and one that uses `async`/`await`. This bundle
6+
exists to test SymbolKit's "alternate declarations" mechanism and ensure that Swift-DocC converts it
7+
into a Declarations section with both declarations.
8+
9+
<!-- Copyright (c) 2023 Apple Inc and the Swift Project authors. All Rights Reserved. -->

0 commit comments

Comments
 (0)