Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
28b9522
Add bundle identifier type that ensures a valid URL host component
d-ronnqvist Oct 22, 2024
0e62ffc
Use new Identifier type in `DocumentationBundle/Info`
d-ronnqvist Oct 22, 2024
b46b5d3
Update code to not use deprecated `Info/identifier` property
d-ronnqvist Oct 22, 2024
bfa673b
Use new Identifier type in `DocumentationBundle`
d-ronnqvist Oct 22, 2024
98c6a58
Update code to not use deprecated `identifier` property
d-ronnqvist Oct 22, 2024
399ed9a
Use new Identifier type in `[Unresolved|Resolved]TopicReference`
d-ronnqvist Oct 22, 2024
a7310b7
Update code to not use deprecated topic reference `bundleIdentifier` …
d-ronnqvist Oct 22, 2024
221891a
Deprecate `BundleIdentifier` in favor of `DocumentationBundle/Identif…
d-ronnqvist Oct 22, 2024
890e323
Use new Identifier type in `BuildMetadata`
d-ronnqvist Oct 22, 2024
3c56a2d
Use new Identifier type in `AssetReference`
d-ronnqvist Oct 22, 2024
13b11fb
Use new Identifier type in `ResourceReference`
d-ronnqvist Oct 22, 2024
414ef9c
Use new Identifier type in `ConvertServiceFallbackResolver`
d-ronnqvist Oct 22, 2024
61cc5e2
Use new Identifier type in `SerializableLinkResolutionInformation`
d-ronnqvist Oct 22, 2024
5369b1c
Use new Identifier type in `ConvertAction/Indexer`
d-ronnqvist Oct 22, 2024
4805a05
Prefer `bundleID` over `id` for types that scoped inside bundle
d-ronnqvist Oct 22, 2024
0f2f8ef
Merge branch 'main' into validate-bundle-identifier
d-ronnqvist Oct 31, 2024
c2442bc
Merge branch 'main' into validate-bundle-identifier
d-ronnqvist Nov 11, 2024
71b27b6
Merge branch 'main' into validate-bundle-identifier
d-ronnqvist Nov 19, 2024
3d063ef
Merge branch 'main' into validate-bundle-identifier
d-ronnqvist Nov 21, 2024
f97e6d3
Use `bundleID` instead of `id` for property names outside the bundle
d-ronnqvist Nov 21, 2024
9478d47
Use "bundle id" in local variable in fallback resolver
d-ronnqvist Nov 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,19 @@ extension DocumentationContext {

@available(*, deprecated, renamed: "configuration.externalDocumentationConfiguration.sources", message: "Use 'configuration.externalDocumentationConfiguration.sources' instead. This deprecated API will be removed after Swift 6.2 is released.")
public var externalDocumentationSources: [BundleIdentifier: ExternalDocumentationSource] {
get { configuration.externalDocumentationConfiguration.sources }
set { configuration.externalDocumentationConfiguration.sources = newValue }
get {
var result = [BundleIdentifier: ExternalDocumentationSource]()
for (key, value) in configuration.externalDocumentationConfiguration.sources {
result[key.rawValue] = value
}
return result
}
set {
configuration.externalDocumentationConfiguration.sources.removeAll()
for (key, value) in newValue {
configuration.externalDocumentationConfiguration.sources[.init(rawValue: key)] = value
}
}
Comment on lines +21 to +33
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this code change needed as part of this PR? this seems to be handling separate logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the storage that this was accessing to changed from [String: ExternalDocumentationSource] to [DocumentationBundle.Identifier: ExternalDocumentationSource] it needs to map all the keys of the storage to and from keys any read or write access to this deprecated property.

}

@available(*, deprecated, renamed: "configuration.externalDocumentationConfiguration.globalSymbolResolver", message: "Use 'configuration.externalDocumentationConfiguration.globalSymbolResolver' instead. This deprecated API will be removed after Swift 6.2 is released.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ extension DocumentationContext {
/// A collection of configuration related to external sources of documentation.
public struct ExternalDocumentationConfiguration {
/// The lookup of external documentation sources by their bundle identifiers.
public var sources: [BundleIdentifier: ExternalDocumentationSource] = [:]
public var sources: [DocumentationBundle.Identifier: ExternalDocumentationSource] = [:]
/// A type that resolves all symbols that are referenced in symbol graph files but can't be found in any of the locally available symbol graph files.
public var globalSymbolResolver: GlobalExternalSymbolResolver?
/// A list of URLs to documentation archives that the local documentation depends on.
Expand Down
46 changes: 31 additions & 15 deletions Sources/SwiftDocC/Infrastructure/DocumentationContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public protocol DocumentationContextDataProviderDelegate: AnyObject {
/// This value is typically a reverse host name, for example: `com.<organization-name>.<product-name>`.
///
/// Documentation links may include the bundle identifier---as a host component of the URL---to reference content in a specific documentation bundle.
@available(*, deprecated, renamed: "DocumentationBundle.Identifier", message: "Use 'DocumentationBundle.Identifier' instead. This deprecated API will be removed after 6.2 is released")
public typealias BundleIdentifier = String

/// The documentation context manages the in-memory model for the built documentation.
Expand Down Expand Up @@ -354,7 +355,7 @@ public class DocumentationContext {
/// - bundle: The bundle that was removed.
@available(*, deprecated, message: "Pass the context its inputs at initialization instead. This deprecated API will be removed after 6.2 is released")
public func dataProvider(_ dataProvider: DocumentationContextDataProvider, didRemoveBundle bundle: DocumentationBundle) throws {
linkResolver.localResolver?.unregisterBundle(identifier: bundle.identifier)
linkResolver.localResolver?.unregisterBundle(identifier: bundle.id)

// Purge the reference cache for this bundle and disable reference caching for
// this bundle moving forward.
Expand Down Expand Up @@ -482,7 +483,7 @@ public class DocumentationContext {
/// - Parameters:
/// - references: A list of references to local nodes to visit to collect links.
/// - localBundleID: The local bundle ID, used to identify and skip absolute fully qualified local links.
private func preResolveExternalLinks(references: [ResolvedTopicReference], localBundleID: BundleIdentifier) {
private func preResolveExternalLinks(references: [ResolvedTopicReference], localBundleID: DocumentationBundle.Identifier) {
preResolveExternalLinks(semanticObjects: references.compactMap({ reference -> ReferencedSemanticObject? in
guard let node = try? entity(with: reference), let semantic = node.semantic else { return nil }
return (reference: reference, semantic: semantic)
Expand All @@ -504,11 +505,11 @@ public class DocumentationContext {
/// - Parameters:
/// - semanticObjects: A list of semantic objects to visit to collect links.
/// - localBundleID: The local bundle ID, used to identify and skip absolute fully qualified local links.
private func preResolveExternalLinks(semanticObjects: [ReferencedSemanticObject], localBundleID: BundleIdentifier) {
private func preResolveExternalLinks(semanticObjects: [ReferencedSemanticObject], localBundleID: DocumentationBundle.Identifier) {
// If there are no external resolvers added we will not resolve any links.
guard !configuration.externalDocumentationConfiguration.sources.isEmpty else { return }

let collectedExternalLinks = Synchronized([String: Set<UnresolvedTopicReference>]())
let collectedExternalLinks = Synchronized([DocumentationBundle.Identifier: Set<UnresolvedTopicReference>]())
semanticObjects.concurrentPerform { _, semantic in
autoreleasepool {
// Walk the node and extract external link references.
Expand Down Expand Up @@ -1407,7 +1408,7 @@ public class DocumentationContext {
}

// Resolve any external references first
preResolveExternalLinks(references: Array(moduleReferences.values) + combinedSymbols.keys.compactMap({ documentationCache.reference(symbolID: $0) }), localBundleID: bundle.id.rawValue)
preResolveExternalLinks(references: Array(moduleReferences.values) + combinedSymbols.keys.compactMap({ documentationCache.reference(symbolID: $0) }), localBundleID: bundle.id)

// Look up and add symbols that are _referenced_ in the symbol graph but don't exist in the symbol graph.
try resolveExternalSymbols(in: combinedSymbols, relationships: combinedRelationshipsBySelector)
Expand Down Expand Up @@ -1798,26 +1799,41 @@ public class DocumentationContext {

/// Returns a list of all the image assets that registered for a given `bundleIdentifier`.
///
/// - Parameter bundleIdentifier: The identifier of the bundle to return image assets for.
/// - Parameter id: The identifier of the bundle to return image assets for.
/// - Returns: A list of all the image assets for the given bundle.
public func registeredImageAssets(for id: DocumentationBundle.Identifier) -> [DataAsset] {
registeredAssets(withExtensions: DocumentationContext.supportedImageExtensions, forBundleID: id)
}

@available(*, deprecated, renamed: "registeredImageAssets(for:)", message: "registeredImageAssets(for:)' instead. This deprecated API will be removed after 6.2 is released")
public func registeredImageAssets(forBundleID bundleIdentifier: BundleIdentifier) -> [DataAsset] {
return registeredAssets(withExtensions: DocumentationContext.supportedImageExtensions, forBundleID: DocumentationBundle.Identifier(rawValue: bundleIdentifier))
registeredImageAssets(for: DocumentationBundle.Identifier(rawValue: bundleIdentifier))
}

/// Returns a list of all the video assets that registered for a given `bundleIdentifier`.
///
/// - Parameter bundleIdentifier: The identifier of the bundle to return video assets for.
/// - Parameter id: The identifier of the bundle to return video assets for.
/// - Returns: A list of all the video assets for the given bundle.
public func registeredVideoAssets(for id: DocumentationBundle.Identifier) -> [DataAsset] {
registeredAssets(withExtensions: DocumentationContext.supportedVideoExtensions, forBundleID: id)
}

@available(*, deprecated, renamed: "registeredVideoAssets(for:)", message: "registeredImageAssets(for:)' instead. This deprecated API will be removed after 6.2 is released")
public func registeredVideoAssets(forBundleID bundleIdentifier: BundleIdentifier) -> [DataAsset] {
return registeredAssets(withExtensions: DocumentationContext.supportedVideoExtensions, forBundleID: DocumentationBundle.Identifier(rawValue: bundleIdentifier))
registeredVideoAssets(for: DocumentationBundle.Identifier(rawValue: bundleIdentifier))
}

/// Returns a list of all the download assets that registered for a given `bundleIdentifier`.
///
/// - Parameter bundleIdentifier: The identifier of the bundle to return download assets for.
/// - Parameter id: The identifier of the bundle to return download assets for.
/// - Returns: A list of all the download assets for the given bundle.
public func registeredDownloadsAssets(for id: DocumentationBundle.Identifier) -> [DataAsset] {
registeredAssets(inContexts: [DataAsset.Context.download], forBundleID: id)
}

@available(*, deprecated, renamed: "registeredDownloadsAssets(for:)", message: "registeredDownloadsAssets(for:)' instead. This deprecated API will be removed after 6.2 is released")
public func registeredDownloadsAssets(forBundleID bundleIdentifier: BundleIdentifier) -> [DataAsset] {
return registeredAssets(inContexts: [DataAsset.Context.download], forBundleID: DocumentationBundle.Identifier(rawValue: bundleIdentifier))
registeredDownloadsAssets(for: DocumentationBundle.Identifier(rawValue: bundleIdentifier))
}

typealias Articles = [DocumentationContext.SemanticResult<Article>]
Expand Down Expand Up @@ -2316,7 +2332,7 @@ public class DocumentationContext {
tutorialTableOfContentsResults.map(referencedSemanticObject) +
tutorials.map(referencedSemanticObject) +
tutorialArticles.map(referencedSemanticObject),
localBundleID: bundle.id.rawValue)
localBundleID: bundle.id)

resolveLinks(
tutorialTableOfContents: tutorialTableOfContentsResults,
Expand Down Expand Up @@ -2358,7 +2374,7 @@ public class DocumentationContext {
// Article curation is only done automatically if there is only one root module
if let rootNode = rootNodeForAutomaticCuration {
let articleReferences = try autoCurateArticles(otherArticles, startingFrom: rootNode)
preResolveExternalLinks(references: articleReferences, localBundleID: bundle.id.rawValue)
preResolveExternalLinks(references: articleReferences, localBundleID: bundle.id)
resolveLinks(curatedReferences: Set(articleReferences), bundle: bundle)
}

Expand All @@ -2373,7 +2389,7 @@ public class DocumentationContext {
linkResolver.localResolver.addAnchorForSymbols(localCache: documentationCache)

// Fifth, resolve links in nodes that are added solely via curation
preResolveExternalLinks(references: Array(allCuratedReferences), localBundleID: bundle.id.rawValue)
preResolveExternalLinks(references: Array(allCuratedReferences), localBundleID: bundle.id)
resolveLinks(curatedReferences: allCuratedReferences, bundle: bundle)

if configuration.convertServiceConfiguration.fallbackResolver != nil {
Expand Down Expand Up @@ -2722,7 +2738,7 @@ public class DocumentationContext {
}

private func externalEntity(with reference: ResolvedTopicReference) -> LinkResolver.ExternalEntity? {
return configuration.externalDocumentationConfiguration.sources[reference.id.rawValue].map({ $0.entity(with: reference) })
return configuration.externalDocumentationConfiguration.sources[reference.id].map({ $0.entity(with: reference) })
?? configuration.convertServiceConfiguration.fallbackResolver?.entityIfPreviouslyResolved(with: reference)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ struct DocumentationCurator {
}

// Check if the link has been externally resolved already.
if let bundleID = unresolved.topicURL.components.host,
if let bundleID = unresolved.topicURL.components.host.map({ DocumentationBundle.Identifier(rawValue: $0) }),
context.configuration.externalDocumentationConfiguration.sources[bundleID] != nil || context.configuration.convertServiceConfiguration.fallbackResolver != nil {
if case .success(let resolvedExternalReference) = context.externallyResolvedLinks[unresolved.topicURL] {
return resolvedExternalReference
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ final class PathHierarchyBasedLinkResolver {
}

/// Remove all matches from a given documentation bundle from the link resolver.
func unregisterBundle(identifier: BundleIdentifier) {
let identifier = DocumentationBundle.Identifier(rawValue: identifier)
func unregisterBundle(identifier: DocumentationBundle.Identifier) {
var newMap = BidirectionalMap<ResolvedIdentifier, ResolvedTopicReference>()
for (id, reference) in resolvedReferenceMap {
if reference.id == identifier {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import Markdown
/// Walks a markup tree and collects any links external to a given bundle.
struct ExternalMarkupReferenceWalker: MarkupVisitor {
/// The local bundle ID, used to identify and skip absolute fully qualified local links.
var localBundleID: BundleIdentifier
var localBundleID: DocumentationBundle.Identifier

/// After walking a markup tree, all encountered external links are collected grouped by the bundle ID.
var collectedExternalLinks = [BundleIdentifier: Set<ValidatedURL>]()
var collectedExternalLinks = [DocumentationBundle.Identifier: Set<ValidatedURL>]()

/// Descends down the given elements' children.
mutating func defaultVisit(_ markup: Markup) {
Expand All @@ -31,7 +31,7 @@ struct ExternalMarkupReferenceWalker: MarkupVisitor {
// Only process documentation links to external bundles
guard let destination = link.destination,
let url = ValidatedURL(parsingAuthoredLink: destination)?.requiring(scheme: ResolvedTopicReference.urlScheme),
let bundleID = url.components.host,
let bundleID = url.components.host.map({ DocumentationBundle.Identifier(rawValue: $0) }),
bundleID != localBundleID
else {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ struct ExternalReferenceWalker: SemanticVisitor {
private var markupResolver: ExternalMarkupReferenceWalker

/// Collected unresolved external references, grouped by the bundle ID.
var collectedExternalReferences: [BundleIdentifier: [UnresolvedTopicReference]] {
var collectedExternalReferences: [DocumentationBundle.Identifier: [UnresolvedTopicReference]] {
return markupResolver.collectedExternalLinks.mapValues { links in
links.map(UnresolvedTopicReference.init(topicURL:))
}
}

/// Creates a new semantic walker that collects links to other documentation sources.
/// - Parameter localBundleID: The local bundle ID, used to identify and skip absolute fully qualified local links.
init(localBundleID: BundleIdentifier) {
init(localBundleID: DocumentationBundle.Identifier) {
self.markupResolver = ExternalMarkupReferenceWalker(localBundleID: localBundleID)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public struct ConvertAction: AsyncAction {
}

if let outOfProcessResolver {
configuration.externalDocumentationConfiguration.sources[outOfProcessResolver.id.rawValue] = outOfProcessResolver
configuration.externalDocumentationConfiguration.sources[outOfProcessResolver.id] = outOfProcessResolver
configuration.externalDocumentationConfiguration.globalSymbolResolver = outOfProcessResolver
}
configuration.externalDocumentationConfiguration.dependencyArchives = dependencies
Expand Down Expand Up @@ -288,7 +288,7 @@ public struct ConvertAction: AsyncAction {
indexer: indexer,
enableCustomTemplates: experimentalEnableCustomTemplates,
transformForStaticHostingIndexHTML: transformForStaticHosting ? indexHTML : nil,
bundleIdentifier: bundle.id.rawValue
bundleID: bundle.id
)

if experimentalModifyCatalogWithGeneratedCuration, let catalogURL = rootURL {
Expand Down Expand Up @@ -422,7 +422,7 @@ public struct ConvertAction: AsyncAction {
context: context,
indexer: nil,
transformForStaticHostingIndexHTML: nil,
bundleIdentifier: bundle.id.rawValue
bundleID: bundle.id
)

try outputConsumer.consume(benchmarks: Benchmark.main)
Expand Down
Loading