@@ -110,11 +110,8 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
110
110
}
111
111
}
112
112
113
- /// A link resolver that resolves references by finding them in path hierarchy.
114
- ///
115
- /// The link resolver is `nil` until some documentation content is registered with the context.
116
- /// It's safe to access the link resolver during symbol registration and at later points in the registration and conversion.
117
- var hierarchyBasedLinkResolver : PathHierarchyBasedLinkResolver ! = nil
113
+ /// A class that resolves documentation links by orchestrating calls to other link resolver implementations.
114
+ public var linkResolver = LinkResolver ( )
118
115
119
116
/// The provider of documentation bundles for this context.
120
117
var dataProvider : DocumentationContextDataProvider
@@ -200,6 +197,8 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
200
197
/// A list of non-topic links that can be resolved.
201
198
var nodeAnchorSections = [ ResolvedTopicReference: AnchorSection] ( )
202
199
200
+ var externalCache = [ ResolvedTopicReference: LinkResolver . ExternalEntity] ( )
201
+
203
202
/// A list of all the problems that was encountered while registering and processing the documentation bundles in this context.
204
203
public var problems : [ Problem ] {
205
204
return diagnosticEngine. problems
@@ -361,7 +360,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
361
360
/// - dataProvider: The provider that removed this bundle.
362
361
/// - bundle: The bundle that was removed.
363
362
public func dataProvider( _ dataProvider: DocumentationContextDataProvider , didRemoveBundle bundle: DocumentationBundle ) throws {
364
- hierarchyBasedLinkResolver ? . unregisterBundle ( identifier: bundle. identifier)
363
+ linkResolver . localResolver ? . unregisterBundle ( identifier: bundle. identifier)
365
364
366
365
// Purge the reference cache for this bundle and disable reference caching for
367
366
// this bundle moving forward.
@@ -1153,7 +1152,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
1153
1152
var moduleReferences = [ String: ResolvedTopicReference] ( )
1154
1153
1155
1154
// Build references for all symbols in all of this module's symbol graphs.
1156
- let symbolReferences = hierarchyBasedLinkResolver . referencesForSymbols ( in: symbolGraphLoader. unifiedGraphs, bundle: bundle, context: self )
1155
+ let symbolReferences = linkResolver . localResolver . referencesForSymbols ( in: symbolGraphLoader. unifiedGraphs, bundle: bundle, context: self )
1157
1156
1158
1157
// Set the index and cache storage capacity to avoid ad-hoc storage resizing.
1159
1158
symbolIndex. reserveCapacity ( symbolReferences. count)
@@ -1270,7 +1269,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
1270
1269
// Only add the symbol mapping now if the path hierarchy based resolver is the main implementation.
1271
1270
// If it is only used for mismatch checking then we must wait until the documentation cache code path has traversed and updated all the colliding nodes.
1272
1271
// Otherwise the mappings will save the unmodified references and the hierarchy based resolver won't find the expected parent nodes when resolving links.
1273
- hierarchyBasedLinkResolver . addMappingForSymbols ( symbolIndex: symbolIndex)
1272
+ linkResolver . localResolver . addMappingForSymbols ( symbolIndex: symbolIndex)
1274
1273
1275
1274
// Track the symbols that have multiple matching documentation extension files for diagnostics.
1276
1275
var symbolsWithMultipleDocumentationExtensionMatches = [ ResolvedTopicReference : [ SemanticResult < Article > ] ] ( )
@@ -1817,7 +1816,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
1817
1816
topicGraph. addNode ( graphNode)
1818
1817
documentationCache [ reference] = documentation
1819
1818
1820
- hierarchyBasedLinkResolver . addRootArticle ( article, anchorSections: documentation. anchorSections)
1819
+ linkResolver . localResolver . addRootArticle ( article, anchorSections: documentation. anchorSections)
1821
1820
for anchor in documentation. anchorSections {
1822
1821
nodeAnchorSections [ anchor. reference] = anchor
1823
1822
}
@@ -1873,7 +1872,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
1873
1872
let graphNode = TopicGraph . Node ( reference: reference, kind: . article, source: . file( url: article. source) , title: title)
1874
1873
topicGraph. addNode ( graphNode)
1875
1874
1876
- hierarchyBasedLinkResolver . addArticle ( article, anchorSections: documentation. anchorSections)
1875
+ linkResolver . localResolver . addArticle ( article, anchorSections: documentation. anchorSections)
1877
1876
for anchor in documentation. anchorSections {
1878
1877
nodeAnchorSections [ anchor. reference] = anchor
1879
1878
}
@@ -2078,6 +2077,17 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
2078
2077
}
2079
2078
}
2080
2079
2080
+ discoveryGroup. async ( queue: discoveryQueue) { [ unowned self] in
2081
+ do {
2082
+ try linkResolver. loadExternalResolvers ( )
2083
+ } catch {
2084
+ // Pipe the error out of the dispatch queue.
2085
+ discoveryError. sync ( {
2086
+ if $0 == nil { $0 = error }
2087
+ } )
2088
+ }
2089
+ }
2090
+
2081
2091
discoveryGroup. wait ( )
2082
2092
2083
2093
try shouldContinueRegistration ( )
@@ -2128,7 +2138,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
2128
2138
options = globalOptions. first
2129
2139
}
2130
2140
2131
- self . hierarchyBasedLinkResolver = hierarchyBasedResolver
2141
+ self . linkResolver . localResolver = hierarchyBasedResolver
2132
2142
hierarchyBasedResolver. addMappingForRoots ( bundle: bundle)
2133
2143
for tutorial in tutorials {
2134
2144
hierarchyBasedResolver. addTutorial ( tutorial)
@@ -2187,7 +2197,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
2187
2197
}
2188
2198
2189
2199
try shouldContinueRegistration ( )
2190
- var allCuratedReferences = try crawlSymbolCuration ( in: hierarchyBasedLinkResolver . topLevelSymbols ( ) , bundle: bundle)
2200
+ var allCuratedReferences = try crawlSymbolCuration ( in: linkResolver . localResolver . topLevelSymbols ( ) , bundle: bundle)
2191
2201
2192
2202
// Store the list of manually curated references if doc coverage is on.
2193
2203
if shouldStoreManuallyCuratedReferences {
@@ -2222,7 +2232,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
2222
2232
// Emit warnings for any remaining uncurated files.
2223
2233
emitWarningsForUncuratedTopics ( )
2224
2234
2225
- hierarchyBasedLinkResolver . addAnchorForSymbols ( symbolIndex: symbolIndex, documentationCache: documentationCache)
2235
+ linkResolver . localResolver . addAnchorForSymbols ( symbolIndex: symbolIndex, documentationCache: documentationCache)
2226
2236
2227
2237
// Fifth, resolve links in nodes that are added solely via curation
2228
2238
try preResolveExternalLinks ( references: Array ( allCuratedReferences) , bundle: bundle)
@@ -2329,7 +2339,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
2329
2339
/// - Returns: An ordered list of symbol references that have been added to the topic graph automatically.
2330
2340
private func autoCurateSymbolsInTopicGraph( engine: DiagnosticEngine ) -> [ ( child: ResolvedTopicReference , parent: ResolvedTopicReference ) ] {
2331
2341
var automaticallyCuratedSymbols = [ ( ResolvedTopicReference, ResolvedTopicReference) ] ( )
2332
- hierarchyBasedLinkResolver . traverseSymbolAndParentPairs { reference, parentReference in
2342
+ linkResolver . localResolver . traverseSymbolAndParentPairs { reference, parentReference in
2333
2343
guard let topicGraphNode = topicGraph. nodeWithReference ( reference) ,
2334
2344
let topicGraphParentNode = topicGraph. nodeWithReference ( parentReference) ,
2335
2345
// Check that the node hasn't got any parents from manual curation
@@ -2535,6 +2545,9 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
2535
2545
let referenceWithoutFragment = reference. withFragment ( nil )
2536
2546
return try entity ( with: referenceWithoutFragment) . availableSourceLanguages
2537
2547
} catch ContextError . notFound {
2548
+ if let externalEntity = externalCache [ reference] {
2549
+ return externalEntity. sourceLanguages
2550
+ }
2538
2551
preconditionFailure ( " Reference does not have an associated documentation node. " )
2539
2552
} catch {
2540
2553
fatalError ( " Unexpected error when retrieving source languages: \( error) " )
@@ -2646,7 +2659,8 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
2646
2659
public func resolve( _ reference: TopicReference , in parent: ResolvedTopicReference , fromSymbolLink isCurrentlyResolvingSymbolLink: Bool = false ) -> TopicReferenceResolutionResult {
2647
2660
switch reference {
2648
2661
case . unresolved( let unresolvedReference) :
2649
- return hierarchyBasedLinkResolver. resolve ( unresolvedReference, in: parent, fromSymbolLink: isCurrentlyResolvingSymbolLink, context: self )
2662
+ return linkResolver. resolve ( unresolvedReference, in: parent, fromSymbolLink: isCurrentlyResolvingSymbolLink, context: self )
2663
+
2650
2664
case . resolved( let resolved) :
2651
2665
// This reference is already resolved (either as a success or a failure), so don't change anything.
2652
2666
return resolved
0 commit comments