Skip to content

Commit 8855506

Browse files
committed
Filter automatic See Alsos based on language
For automatically-generated See Also sections, filter out topics that are not available in the parent's current language. rdar://90168171
1 parent bef86be commit 8855506

File tree

8 files changed

+388
-103
lines changed

8 files changed

+388
-103
lines changed

Sources/SwiftDocC/Infrastructure/Topic Graph/AutomaticCuration.swift

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,14 @@ public struct AutomaticCuration {
115115
/// - bundle: A documentation bundle.
116116
/// - Returns: A group title and the group's references or links.
117117
/// `nil` if the method can't find any relevant links to automatically generate a See Also content.
118-
static func seeAlso(for node: DocumentationNode, context: DocumentationContext, bundle: DocumentationBundle, renderContext: RenderContext?, renderer: DocumentationContentRenderer) throws -> TaskGroup? {
118+
static func seeAlso(
119+
for node: DocumentationNode,
120+
withTrait variantsTrait: DocumentationDataVariantsTrait,
121+
context: DocumentationContext,
122+
bundle: DocumentationBundle,
123+
renderContext: RenderContext?,
124+
renderer: DocumentationContentRenderer
125+
) throws -> TaskGroup? {
119126
// First try getting the canonical path from a render context, default to the documentation context
120127
guard let canonicalPath = renderContext?.store.content(for: node.reference)?.canonicalPath ?? context.pathsTo(node.reference).first,
121128
!canonicalPath.isEmpty else {
@@ -125,6 +132,19 @@ public struct AutomaticCuration {
125132

126133
let parentReference = canonicalPath.last!
127134

135+
func filterReferences(_ references: [ResolvedTopicReference]) throws -> [ResolvedTopicReference] {
136+
try references
137+
// Don't include the current node.
138+
.filter { $0 != node.reference }
139+
140+
// Filter out nodes that aren't available in the given trait.
141+
.filter { reference in
142+
try context.entity(with: reference)
143+
.availableVariantTraits
144+
.contains(variantsTrait)
145+
}
146+
}
147+
128148
// Look up the render context first
129149
if let taskGroups = renderContext?.store.content(for: parentReference)?.taskGroups,
130150
let linkingGroup = taskGroups
@@ -134,7 +154,7 @@ public struct AutomaticCuration {
134154
{
135155
// Group match in render context, verify if there are any other references besides the current one.
136156
guard linkingGroup.references.count > 1 else { return nil }
137-
return (title: linkingGroup.title, references: linkingGroup.references.filter { $0 != node.reference })
157+
return (title: linkingGroup.title, references: try filterReferences(linkingGroup.references))
138158
}
139159

140160
// Get the parent's task groups
@@ -152,7 +172,7 @@ public struct AutomaticCuration {
152172
return nil
153173
}
154174

155-
return (title: group.title, references: group.references.filter { $0 != node.reference })
175+
return (title: group.title, references: try filterReferences(group.references))
156176
}
157177
}
158178

Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -661,15 +661,18 @@ public struct RenderNodeTranslator: SemanticVisitor {
661661
// Automatic groups are named after the child's kind, e.g.
662662
// "Methods", "Variables", etc.
663663
let alreadyCurated = Set(node.topicSections.flatMap { $0.identifiers })
664-
let groups = try! AutomaticCuration.topics(for: documentationNode, withTrait: nil, context: context)
665-
.compactMap({ group -> AutomaticCuration.TaskGroup? in
666-
// Remove references that have been already curated.
667-
let newReferences = group.references.filter { !alreadyCurated.contains($0.absoluteString) }
668-
// Remove groups that have no uncurated references
669-
guard !newReferences.isEmpty else { return nil }
670-
671-
return (title: group.title, references: newReferences)
672-
})
664+
let groups = try! AutomaticCuration.topics(
665+
for: documentationNode,
666+
withTrait: trait,
667+
context: context
668+
).compactMap { group -> AutomaticCuration.TaskGroup? in
669+
// Remove references that have been already curated.
670+
let newReferences = group.references.filter { !alreadyCurated.contains($0.absoluteString) }
671+
// Remove groups that have no uncurated references
672+
guard !newReferences.isEmpty else { return nil }
673+
674+
return (title: group.title, references: newReferences)
675+
}
673676

674677
// Collect all child topic references.
675678
contentCompiler.collectedTopicReferences.append(contentsOf: groups.flatMap(\.references))
@@ -719,6 +722,7 @@ public struct RenderNodeTranslator: SemanticVisitor {
719722
// Automatic See Also section
720723
if let seeAlso = try! AutomaticCuration.seeAlso(
721724
for: documentationNode,
725+
withTrait: trait,
722726
context: context,
723727
bundle: bundle,
724728
renderContext: renderContext,
@@ -1309,6 +1313,7 @@ public struct RenderNodeTranslator: SemanticVisitor {
13091313
// Curate the current node's siblings as further See Also groups.
13101314
if let seeAlso = try! AutomaticCuration.seeAlso(
13111315
for: documentationNode,
1316+
withTrait: trait,
13121317
context: context,
13131318
bundle: bundle,
13141319
renderContext: renderContext,

Tests/SwiftDocCTests/Indexing/RenderIndexTests.swift

Lines changed: 71 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,47 @@ final class RenderIndexTests: XCTestCase {
7777
"title": "_MixedLanguageFrameworkVersionNumber",
7878
"type": "var"
7979
},
80+
{
81+
"title": "Some Swift-only APIs, some Objective-C–only APIs, some mixed",
82+
"type": "groupMarker"
83+
},
84+
{
85+
"path": "\/documentation\/mixedlanguageframework\/_mixedlanguageframeworkversionstring",
86+
"title": "_MixedLanguageFrameworkVersionString",
87+
"type": "var"
88+
},
89+
{
90+
"children": [
91+
{
92+
"title": "Type Methods",
93+
"type": "groupMarker"
94+
},
95+
{
96+
"children": [
97+
{
98+
"title": "Custom",
99+
"type": "groupMarker"
100+
},
101+
{
102+
"path": "\/documentation\/mixedlanguageframework\/foo-occ.typealias",
103+
"title": "Foo",
104+
"type": "typealias"
105+
}
106+
],
107+
"path": "\/documentation\/mixedlanguageframework\/bar\/mystringfunction(_:)",
108+
"title": "myStringFunction:error: (navigator title)",
109+
"type": "method"
110+
}
111+
],
112+
"path": "\/documentation\/mixedlanguageframework\/bar",
113+
"title": "Bar",
114+
"type": "class"
115+
},
116+
{
117+
"title": "Article",
118+
"path": "/documentation/mixedlanguageframework/article",
119+
"type": "article"
120+
},
80121
{
81122
"title": "Tutorials",
82123
"type": "groupMarker"
@@ -137,46 +178,6 @@ final class RenderIndexTests: XCTestCase {
137178
}
138179
]
139180
},
140-
{
141-
"title": "Classes",
142-
"type": "groupMarker"
143-
},
144-
{
145-
"children": [
146-
{
147-
"title": "Type Methods",
148-
"type": "groupMarker"
149-
},
150-
{
151-
"children": [
152-
{
153-
"title": "Custom",
154-
"type": "groupMarker"
155-
},
156-
{
157-
"path": "\/documentation\/mixedlanguageframework\/foo-occ.typealias",
158-
"title": "Foo",
159-
"type": "typealias"
160-
}
161-
],
162-
"path": "\/documentation\/mixedlanguageframework\/bar\/mystringfunction(_:)",
163-
"title": "myStringFunction:error: (navigator title)",
164-
"type": "method"
165-
}
166-
],
167-
"path": "\/documentation\/mixedlanguageframework\/bar",
168-
"title": "Bar",
169-
"type": "class"
170-
},
171-
{
172-
"title": "Variables",
173-
"type": "groupMarker"
174-
},
175-
{
176-
"path": "\/documentation\/mixedlanguageframework\/_mixedlanguageframeworkversionstring",
177-
"title": "_MixedLanguageFrameworkVersionString",
178-
"type": "var"
179-
},
180181
{
181182
"title": "Enumerations",
182183
"type": "groupMarker"
@@ -234,6 +235,36 @@ final class RenderIndexTests: XCTestCase {
234235
"title": "SwiftOnlyStruct",
235236
"type": "struct"
236237
},
238+
{
239+
"title": "Some Swift-only APIs, some Objective-C–only APIs, some mixed",
240+
"type": "groupMarker"
241+
},
242+
{
243+
"path": "\/documentation\/mixedlanguageframework\/swiftonlyclass",
244+
"title": "SwiftOnlyClass",
245+
"type": "class"
246+
},
247+
{
248+
"children": [
249+
{
250+
"title": "Type Methods",
251+
"type": "groupMarker"
252+
},
253+
{
254+
"path": "\/documentation\/mixedlanguageframework\/bar\/mystringfunction(_:)",
255+
"title": "class func myStringFunction(String) throws -> String",
256+
"type": "method"
257+
}
258+
],
259+
"path": "\/documentation\/mixedlanguageframework\/bar",
260+
"title": "Bar",
261+
"type": "class"
262+
},
263+
{
264+
"title": "Article",
265+
"path": "/documentation/mixedlanguageframework/article",
266+
"type": "article"
267+
},
237268
{
238269
"title": "Tutorials",
239270
"type": "groupMarker"
@@ -305,26 +336,6 @@ final class RenderIndexTests: XCTestCase {
305336
}
306337
]
307338
},
308-
{
309-
"title": "Classes",
310-
"type": "groupMarker"
311-
},
312-
{
313-
"children": [
314-
{
315-
"title": "Type Methods",
316-
"type": "groupMarker"
317-
},
318-
{
319-
"path": "\/documentation\/mixedlanguageframework\/bar\/mystringfunction(_:)",
320-
"title": "class func myStringFunction(String) throws -> String",
321-
"type": "method"
322-
}
323-
],
324-
"path": "\/documentation\/mixedlanguageframework\/bar",
325-
"title": "Bar",
326-
"type": "class"
327-
},
328339
{
329340
"title": "Structures",
330341
"type": "groupMarker"

Tests/SwiftDocCTests/Infrastructure/AutomaticCurationTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,12 @@ class AutomaticCurationTests: XCTestCase {
376376
[
377377
"Classes",
378378
"/documentation/MixedLanguageFramework/Bar",
379+
"/documentation/MixedLanguageFramework/SwiftOnlyClass",
379380

380381
"Structures",
381382
"/documentation/MixedLanguageFramework/Foo-swift.struct",
382383

383-
// SwiftOnlyStruct is manually curated.
384+
// SwiftOnlyStruct is manually curated in APICollection.md.
384385
// "/documentation/MixedLanguageFramework/SwiftOnlyStruct",
385386
]
386387
)
@@ -401,7 +402,7 @@ class AutomaticCurationTests: XCTestCase {
401402

402403
"Variables",
403404

404-
// _MixedLanguageFrameworkVersionNumber is manually curated.
405+
// _MixedLanguageFrameworkVersionNumber is manually curated in APICollection.md.
405406
// "/documentation/MixedLanguageFramework/_MixedLanguageFrameworkVersionNumber",
406407

407408
"/documentation/MixedLanguageFramework/_MixedLanguageFrameworkVersionString",

0 commit comments

Comments
 (0)