|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 | 13 | package import Foundation
|
14 |
| -@preconcurrency import SwiftDocC |
| 14 | +@_spi(LinkCompletion) @preconcurrency import SwiftDocC |
15 | 15 |
|
16 | 16 | final actor DocCCatalogIndexManager {
|
17 | 17 | private let server: DocCServer
|
@@ -74,63 +74,74 @@ package enum DocCIndexError: LocalizedError {
|
74 | 74 | }
|
75 | 75 |
|
76 | 76 | package struct DocCCatalogIndex: Sendable {
|
77 |
| - private let assetReferenceToDataAsset: [String: DataAsset] |
78 |
| - private let documentationExtensionToSourceURL: [DocCSymbolLink: URL] |
79 |
| - let articlePathToSourceURLAndReference: [String: (URL, TopicRenderReference)] |
80 |
| - let tutorialPathToSourceURLAndReference: [String: (URL, TopicRenderReference)] |
81 |
| - let tutorialOverviewPathToSourceURLAndReference: [String: (URL, TopicRenderReference)] |
82 |
| - |
83 |
| - func asset(for assetReference: AssetReference) -> DataAsset? { |
84 |
| - assetReferenceToDataAsset[assetReference.assetName] |
85 |
| - } |
| 77 | + /// A map from an asset name to its DataAsset contents. |
| 78 | + let assets: [String: DataAsset] |
| 79 | + |
| 80 | + /// An array of DocCSymbolLink and their associated document URLs. |
| 81 | + let documentationExtensions: [(link: DocCSymbolLink, documentURL: URL?)] |
| 82 | + |
| 83 | + /// A map from article name to its TopicRenderReference. |
| 84 | + let articles: [String: TopicRenderReference] |
| 85 | + |
| 86 | + /// A map from tutorial name to its TopicRenderReference. |
| 87 | + let tutorials: [String: TopicRenderReference] |
86 | 88 |
|
87 |
| - package func documentationExtension(for symbolLink: DocCSymbolLink) -> URL? { |
88 |
| - return documentationExtensionToSourceURL[symbolLink] |
| 89 | + // A map from tutorial overview name to its TopicRenderReference. |
| 90 | + let tutorialOverviews: [String: TopicRenderReference] |
| 91 | + |
| 92 | + /// Retrieves the documentation extension URL for the given symbol if one exists. |
| 93 | + /// |
| 94 | + /// - Parameter symbolInformation: The `DocCSymbolInformation` representing the symbol to search for. |
| 95 | + package func documentationExtension(for symbolInformation: DocCSymbolInformation) -> URL? { |
| 96 | + documentationExtensions.filter { symbolInformation.matches($0.link) }.first?.documentURL |
89 | 97 | }
|
90 | 98 |
|
91 | 99 | init(from renderReferenceStore: RenderReferenceStore) {
|
92 | 100 | // Assets
|
93 |
| - var assetReferenceToDataAsset: [String: DataAsset] = [:] |
| 101 | + var assets: [String: DataAsset] = [:] |
94 | 102 | for (reference, asset) in renderReferenceStore.assets {
|
95 | 103 | var asset = asset
|
96 | 104 | asset.variants = asset.variants.compactMapValues { $0.withScheme("doc-asset") }
|
97 |
| - assetReferenceToDataAsset[reference.assetName] = asset |
| 105 | + assets[reference.assetName] = asset |
98 | 106 | }
|
99 |
| - self.assetReferenceToDataAsset = assetReferenceToDataAsset |
| 107 | + self.assets = assets |
100 | 108 | // Markdown and Tutorial content
|
101 |
| - var documentationExtensionToSourceURL: [DocCSymbolLink: URL] = [:] |
102 |
| - var articlePathToSourceURLAndReference = [String: (URL, TopicRenderReference)]() |
103 |
| - var tutorialPathToSourceURLAndReference = [String: (URL, TopicRenderReference)]() |
104 |
| - var tutorialOverviewPathToSourceURLAndReference = [String: (URL, TopicRenderReference)]() |
| 109 | + var documentationExtensionToSourceURL: [(link: DocCSymbolLink, documentURL: URL?)] = [] |
| 110 | + var articles: [String: TopicRenderReference] = [:] |
| 111 | + var tutorials: [String: TopicRenderReference] = [:] |
| 112 | + var tutorialOverviews: [String: TopicRenderReference] = [:] |
105 | 113 | for (renderReferenceKey, topicContentValue) in renderReferenceStore.topics {
|
106 |
| - guard let topicRenderReference = topicContentValue.renderReference as? TopicRenderReference, |
107 |
| - let topicContentSource = topicContentValue.source |
108 |
| - else { |
| 114 | + guard let topicRenderReference = topicContentValue.renderReference as? TopicRenderReference else { |
109 | 115 | continue
|
110 | 116 | }
|
| 117 | + // Article and Tutorial URLs in SwiftDocC are always of the form `doc://<BundleID>/<Type>/<ModuleName>/<Filename>`. |
| 118 | + // Therefore, we only really need to store the filename in these cases which will always be the last path component. |
111 | 119 | let lastPathComponent = renderReferenceKey.url.lastPathComponent
|
112 | 120 |
|
113 | 121 | switch topicRenderReference.kind {
|
114 | 122 | case .article:
|
115 |
| - articlePathToSourceURLAndReference[lastPathComponent] = (topicContentSource, topicRenderReference) |
| 123 | + articles[lastPathComponent] = topicRenderReference |
116 | 124 | case .tutorial:
|
117 |
| - tutorialPathToSourceURLAndReference[lastPathComponent] = (topicContentSource, topicRenderReference) |
| 125 | + tutorials[lastPathComponent] = topicRenderReference |
118 | 126 | case .overview:
|
119 |
| - tutorialOverviewPathToSourceURLAndReference[lastPathComponent] = (topicContentSource, topicRenderReference) |
| 127 | + tutorialOverviews[lastPathComponent] = topicRenderReference |
120 | 128 | default:
|
121 |
| - guard topicContentValue.isDocumentationExtensionContent, |
122 |
| - let absoluteSymbolLink = AbsoluteSymbolLink(string: topicContentValue.renderReference.identifier.identifier) |
123 |
| - else { |
| 129 | + guard topicContentValue.isDocumentationExtensionContent else { |
| 130 | + continue |
| 131 | + } |
| 132 | + // Documentation extensions are always of the form `doc://<BundleID>/documentation/<SymbolPath>`. |
| 133 | + // We want to parse the `SymbolPath` in this case and store it in the index for lookups later. |
| 134 | + let linkString = renderReferenceKey.url.pathComponents[2...].joined(separator: "/") |
| 135 | + guard let doccSymbolLink = DocCSymbolLink(linkString: linkString) else { |
124 | 136 | continue
|
125 | 137 | }
|
126 |
| - let doccSymbolLink = DocCSymbolLink(absoluteSymbolLink: absoluteSymbolLink) |
127 |
| - documentationExtensionToSourceURL[doccSymbolLink] = topicContentValue.source |
| 138 | + documentationExtensionToSourceURL.append((link: doccSymbolLink, documentURL: topicContentValue.source)) |
128 | 139 | }
|
129 | 140 | }
|
130 |
| - self.documentationExtensionToSourceURL = documentationExtensionToSourceURL |
131 |
| - self.articlePathToSourceURLAndReference = articlePathToSourceURLAndReference |
132 |
| - self.tutorialPathToSourceURLAndReference = tutorialPathToSourceURLAndReference |
133 |
| - self.tutorialOverviewPathToSourceURLAndReference = tutorialOverviewPathToSourceURLAndReference |
| 141 | + self.documentationExtensions = documentationExtensionToSourceURL |
| 142 | + self.articles = articles |
| 143 | + self.tutorials = tutorials |
| 144 | + self.tutorialOverviews = tutorialOverviews |
134 | 145 | }
|
135 | 146 | }
|
136 | 147 |
|
|
0 commit comments