Skip to content

Commit a50665b

Browse files
committed
Emit language-specific relationships
Use SymbolKit's new relationshipsByLanguage API to emit language-specific relationships, e.g., for symbols that have different conformances in Swift vs. Objective-C. rdar://91627374
1 parent 18cee31 commit a50665b

File tree

8 files changed

+501
-103
lines changed

8 files changed

+501
-103
lines changed

Sources/SwiftDocC/Infrastructure/DocumentationContext.swift

Lines changed: 110 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,7 +1295,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
12951295
/// A tree of the symbol hierarchy as defined by the combined symbol graph.
12961296
var symbolsURLHierarchy = BidirectionalTree<ResolvedTopicReference>(root: bundle.documentationRootReference)
12971297
/// We need only unique relationships so we'll collect them in a set.
1298-
var combinedRelationships = Set<SymbolGraph.Relationship>()
1298+
var combinedRelationships = [UnifiedSymbolGraph.Selector: Set<SymbolGraph.Relationship>]()
12991299
/// Collect symbols from all symbol graphs.
13001300
var combinedSymbols = [String: UnifiedSymbolGraph.Symbol]()
13011301

@@ -1372,13 +1372,20 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
13721372
addSymbolsToTopicGraph(symbolGraph: unifiedSymbolGraph, url: fileURL, symbolReferences: symbolReferences, moduleReference: moduleReference, bundle: bundle)
13731373

13741374
// For inherited symbols we remove the source docs (if inheriting docs is disabled) before creating their documentation nodes.
1375-
for relationship in unifiedSymbolGraph.relationships {
1376-
// Check for an origin key.
1377-
if relationship.mixins[SymbolGraph.Relationship.SourceOrigin.mixinKey] != nil
1378-
// Check if it's a memberOf or implementation relationship.
1379-
&& (relationship.kind == .memberOf || relationship.kind == .defaultImplementationOf) {
1380-
1381-
SymbolGraphRelationshipsBuilder.addInheritedDefaultImplementation(edge: relationship, context: self, symbolIndex: &symbolIndex, engine: diagnosticEngine)
1375+
for (_, relationships) in unifiedSymbolGraph.relationshipsByLanguage {
1376+
for relationship in relationships {
1377+
// Check for an origin key.
1378+
if relationship.mixins[SymbolGraph.Relationship.SourceOrigin.mixinKey] != nil
1379+
// Check if it's a memberOf or implementation relationship.
1380+
&& (relationship.kind == .memberOf || relationship.kind == .defaultImplementationOf) {
1381+
1382+
SymbolGraphRelationshipsBuilder.addInheritedDefaultImplementation(
1383+
edge: relationship,
1384+
context: self,
1385+
symbolIndex: &symbolIndex,
1386+
engine: diagnosticEngine
1387+
)
1388+
}
13821389
}
13831390
}
13841391

@@ -1409,33 +1416,45 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
14091416

14101417
// Collect symbols and relationships
14111418
combinedSymbols.merge(unifiedSymbolGraph.symbols, uniquingKeysWith: { $1 })
1412-
combinedRelationships.formUnion(unifiedSymbolGraph.relationships)
1419+
1420+
for (selector, relationships) in unifiedSymbolGraph.relationshipsByLanguage {
1421+
combinedRelationships[selector, default: []].formUnion(relationships)
1422+
}
1423+
1424+
// Keep track of relationships that refer to symbols that are absent from the symbol graph, so that
1425+
// we can diagnose them.
1426+
combinedRelationships[
1427+
.init(interfaceLanguage: "unknown", platform: nil),
1428+
default: []
1429+
].formUnion(unifiedSymbolGraph.orphanRelationships)
14131430
}
14141431

14151432
try shouldContinueRegistration()
1416-
1417-
// Add parent <-> child edges to the URL tree
1418-
try combinedRelationships
1419-
.compactMap(parentChildRelationship(from:))
1420-
.sorted(by: Self.sortRelationshipsPreOrder)
1421-
.forEach({ pair in
1422-
// Add the relationship to the URL hierarchy
1423-
let (parentRef, childRef) = pair
1424-
// If the unique reference already exists, it's been added by another symbol graph
1425-
// likely built for a different target platform, ignore it as it's the exact same symbol.
1426-
if (try? symbolsURLHierarchy.parent(of: childRef)) == nil {
1427-
do {
1428-
try symbolsURLHierarchy.add(childRef, parent: parentRef)
1429-
} catch let error as BidirectionalTree<ResolvedTopicReference>.Error {
1430-
switch error {
1431-
// Some parents might not exist if they are types from other frameworks and
1432-
// those are not pulled into and available in the current symbol graph.
1433-
case .nodeNotFound: break
1434-
default: throw error
1433+
1434+
for (_, relationships) in combinedRelationships {
1435+
// Add parent <-> child edges to the URL tree
1436+
try relationships
1437+
.compactMap(parentChildRelationship(from:))
1438+
.sorted(by: Self.sortRelationshipsPreOrder)
1439+
.forEach({ pair in
1440+
// Add the relationship to the URL hierarchy
1441+
let (parentRef, childRef) = pair
1442+
// If the unique reference already exists, it's been added by another symbol graph
1443+
// likely built for a different target platform, ignore it as it's the exact same symbol.
1444+
if (try? symbolsURLHierarchy.parent(of: childRef)) == nil {
1445+
do {
1446+
try symbolsURLHierarchy.add(childRef, parent: parentRef)
1447+
} catch let error as BidirectionalTree<ResolvedTopicReference>.Error {
1448+
switch error {
1449+
// Some parents might not exist if they are types from other frameworks and
1450+
// those are not pulled into and available in the current symbol graph.
1451+
case .nodeNotFound: break
1452+
default: throw error
1453+
}
14351454
}
14361455
}
1437-
}
1438-
})
1456+
})
1457+
}
14391458

14401459
// Update the children of collision URLs. Walk the tree and update any dependents of updated URLs
14411460
for moduleReference in moduleReferences.values {
@@ -1445,7 +1464,14 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
14451464
}
14461465

14471466
// Create inherited API collections
1448-
try GeneratedDocumentationTopics.createInheritedSymbolsAPICollections(relationships: combinedRelationships, symbolsURLHierarchy: &symbolsURLHierarchy, context: self, bundle: bundle)
1467+
for (_, relationships) in combinedRelationships {
1468+
try GeneratedDocumentationTopics.createInheritedSymbolsAPICollections(
1469+
relationships: relationships,
1470+
symbolsURLHierarchy: &symbolsURLHierarchy,
1471+
context: self,
1472+
bundle: bundle
1473+
)
1474+
}
14491475

14501476
// Parse and prepare the nodes' content concurrently.
14511477
let updatedNodes: [(node: DocumentationNode, matchedArticleURL: URL?)] = Array(symbolIndex.values)
@@ -1487,8 +1513,10 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
14871513
// Look up and add symbols that are _referenced_ in the symbol graph but don't exist in the symbol graph.
14881514
try resolveExternalSymbols(in: combinedSymbols, relationships: combinedRelationships)
14891515

1490-
// Build relationships in the completed graph
1491-
buildRelationships(combinedRelationships, bundle: bundle, engine: diagnosticEngine)
1516+
for (selector, relationships) in combinedRelationships {
1517+
// Build relationships in the completed graph
1518+
buildRelationships(relationships, selector: selector, bundle: bundle, engine: diagnosticEngine)
1519+
}
14921520

14931521
// Index references
14941522
referencesIndex.removeAll()
@@ -1569,32 +1597,70 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
15691597
///
15701598
/// ## See Also
15711599
/// - ``SymbolGraphRelationshipsBuilder``
1572-
func buildRelationships(_ relationships: Set<SymbolGraph.Relationship>, bundle: DocumentationBundle, engine: DiagnosticEngine) {
1600+
func buildRelationships(
1601+
_ relationships: Set<SymbolGraph.Relationship>,
1602+
selector: UnifiedSymbolGraph.Selector,
1603+
bundle: DocumentationBundle,
1604+
engine: DiagnosticEngine
1605+
) {
15731606
for edge in relationships {
15741607
switch edge.kind {
15751608
case .conformsTo:
15761609
// Build conformant type <-> protocol relationships
1577-
SymbolGraphRelationshipsBuilder.addConformanceRelationship(edge: edge, in: bundle, symbolIndex: &symbolIndex, engine: diagnosticEngine)
1610+
SymbolGraphRelationshipsBuilder.addConformanceRelationship(
1611+
edge: edge,
1612+
selector: selector,
1613+
in: bundle,
1614+
symbolIndex: &symbolIndex,
1615+
engine: diagnosticEngine
1616+
)
15781617
case .defaultImplementationOf:
15791618
// Build implementation <-> protocol requirement relationships.
1580-
SymbolGraphRelationshipsBuilder.addImplementationRelationship(edge: edge, in: bundle, context: self, symbolIndex: &symbolIndex, engine: diagnosticEngine)
1619+
SymbolGraphRelationshipsBuilder.addImplementationRelationship(
1620+
edge: edge,
1621+
selector: selector,
1622+
in: bundle,
1623+
context: self,
1624+
symbolIndex: &symbolIndex, engine: diagnosticEngine
1625+
)
15811626
case .inheritsFrom:
15821627
// Build ancestor <-> offspring relationships.
1583-
SymbolGraphRelationshipsBuilder.addInheritanceRelationship(edge: edge, in: bundle, symbolIndex: &symbolIndex, engine: diagnosticEngine)
1628+
SymbolGraphRelationshipsBuilder.addInheritanceRelationship(
1629+
edge: edge,
1630+
selector: selector,
1631+
in: bundle,
1632+
symbolIndex: &symbolIndex,
1633+
engine: diagnosticEngine
1634+
)
15841635
case .requirementOf:
15851636
// Build required member -> protocol relationships.
1586-
SymbolGraphRelationshipsBuilder.addRequirementRelationship(edge: edge, in: bundle, symbolIndex: &symbolIndex, engine: diagnosticEngine)
1637+
SymbolGraphRelationshipsBuilder.addRequirementRelationship(
1638+
edge: edge,
1639+
selector: selector,
1640+
in: bundle,
1641+
symbolIndex: &symbolIndex,
1642+
engine: diagnosticEngine
1643+
)
15871644
case .optionalRequirementOf:
15881645
// Build optional required member -> protocol relationships.
1589-
SymbolGraphRelationshipsBuilder.addOptionalRequirementRelationship(edge: edge, in: bundle, symbolIndex: &symbolIndex, engine: diagnosticEngine)
1646+
SymbolGraphRelationshipsBuilder.addOptionalRequirementRelationship(
1647+
edge: edge,
1648+
selector: selector,
1649+
in: bundle,
1650+
symbolIndex: &symbolIndex,
1651+
engine: diagnosticEngine
1652+
)
15901653
default:
15911654
break
15921655
}
15931656
}
15941657
}
15951658

15961659
/// Look up and add symbols that are _referenced_ in the symbol graph but don't exist in the symbol graph, using an `externalSymbolResolver` (if not `nil`).
1597-
func resolveExternalSymbols(in symbols: [String: UnifiedSymbolGraph.Symbol], relationships: Set<SymbolGraph.Relationship>) throws {
1660+
func resolveExternalSymbols(
1661+
in symbols: [String: UnifiedSymbolGraph.Symbol],
1662+
relationships: [UnifiedSymbolGraph.Selector: Set<SymbolGraph.Relationship>]
1663+
) throws {
15981664
guard let symbolResolver = externalSymbolResolver else {
15991665
return
16001666
}
@@ -1604,8 +1670,10 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
16041670

16051671
// Add all the symbols that are the target of a relationship. These could for example be protocols that are being conformed to,
16061672
// classes that are being subclassed, or methods that are being overridden.
1607-
for edge in relationships where symbolIndex[edge.target] == nil {
1608-
symbolsToResolve.insert(edge.target)
1673+
for (_, relationships) in relationships {
1674+
for edge in relationships where symbolIndex[edge.target] == nil {
1675+
symbolsToResolve.insert(edge.target)
1676+
}
16091677
}
16101678

16111679
// Add all the types that are referenced in a declaration. These could for example be the type of an argument or return value.

Sources/SwiftDocC/Infrastructure/Symbol Graph/Relationship+Hashable.swift

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)