From 59a8290700b8dca79b5799d20303969922d88bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20R=C3=B6nnqvist?= Date: Mon, 22 Sep 2025 18:26:10 +0200 Subject: [PATCH 01/10] Rename documentation bundle to documentation inputs --- .../DocumentationContextConverter.swift | 33 +- .../DocumentationNodeConverter.swift | 17 +- .../Convert/ConvertService+DataProvider.swift | 10 +- .../Convert/ConvertService.swift | 20 +- .../ConvertServiceFallbackResolver.swift | 4 +- .../Services/Convert/ConvertRequest.swift | 6 +- .../Bundle Assets/DataAssetManager.swift | 4 +- .../DocumentationContext+Configuration.swift | 4 +- .../ConvertActionConverter.swift | 18 +- .../ConvertOutputConsumer.swift | 15 +- .../Infrastructure/DocumentationContext.swift | 170 +++---- .../Infrastructure/DocumentationCurator.swift | 14 +- ...wift => DocumentationInputFileTypes.swift} | 6 +- ...t => DocumentationInputs+Identifier.swift} | 16 +- ...Bundle.swift => DocumentationInputs.swift} | 27 +- .../OutOfProcessReferenceResolver.swift | 4 +- .../DocumentationInputsProvider.swift | 10 +- .../LinkResolver+NavigatorIndex.swift | 4 +- .../Link Resolution/LinkResolver.swift | 10 +- .../PathHierarchy+Serialization.swift | 6 +- .../PathHierarchyBasedLinkResolver.swift | 18 +- .../Infrastructure/NodeURLGenerator.swift | 11 +- .../GeneratedDocumentationTopics.swift | 10 +- .../ResolvedTopicReference+Symbol.swift | 10 +- .../Symbol Graph/SymbolGraphLoader.swift | 20 +- .../SymbolGraphRelationshipsBuilder.swift | 20 +- .../UnresolvedTopicReference+Symbol.swift | 8 +- .../Topic Graph/AutomaticCuration.swift | 6 +- .../Workspace/DefaultAvailability.swift | 4 +- .../Workspace/DocumentationBundle+Info.swift | 16 +- .../DocumentationWorkspaceDataProvider.swift | 4 +- .../Workspace/FeatureFlags+Info.swift | 4 +- .../LinkTargets/LinkDestinationSummary.swift | 8 +- Sources/SwiftDocC/Model/BuildMetadata.swift | 4 +- .../SwiftDocC/Model/DocumentationNode.swift | 10 +- Sources/SwiftDocC/Model/Identifier.swift | 20 +- .../DocumentationContentRenderer.swift | 21 +- .../Model/Rendering/LinkTitleResolver.swift | 4 +- .../RenderHierarchyTranslator.swift | 12 +- .../Rendering/RenderContentCompiler.swift | 10 +- .../Rendering/RenderContentConvertible.swift | 2 +- .../Model/Rendering/RenderContext.swift | 17 +- .../Rendering/RenderNodeTranslator.swift | 68 ++- .../Rendering/RenderReferenceStore.swift | 2 +- .../SwiftDocC/Semantics/Article/Article.swift | 10 +- .../Semantics/Article/MarkupConvertible.swift | 4 +- Sources/SwiftDocC/Semantics/Comment.swift | 2 +- .../SwiftDocC/Semantics/ContentAndMedia.swift | 4 +- .../Semantics/DirectiveConvertable.swift | 2 +- .../AutomaticDirectiveConvertible.swift | 25 +- .../DirectiveArgumentWrapper.swift | 18 +- .../DirectiveMirror.swift | 4 +- .../SwiftDocC/Semantics/DirectiveParser.swift | 4 +- .../ExternalMarkupReferenceWalker.swift | 8 +- .../ExternalReferenceWalker.swift | 4 +- .../General Purpose Analyses/Extract.swift | 8 +- .../HasAtLeastOne.swift | 6 +- .../HasAtMostOne.swift | 8 +- .../HasExactlyOne.swift | 14 +- .../HasOnlySequentialHeadings.swift | 2 +- .../Semantics/MarkupReferenceResolver.swift | 16 +- .../Semantics/Metadata/CallToAction.swift | 6 +- .../Semantics/ReferenceResolver.swift | 30 +- .../Semantics/SemanticAnalyzer.swift | 62 +-- .../Semantics/Snippets/Snippet.swift | 2 +- .../Technology/Resources/Resources.swift | 6 +- .../Semantics/Technology/Resources/Tile.swift | 2 +- .../Technology/TutorialTableOfContents.swift | 12 +- .../Semantics/Technology/Volume/Volume.swift | 8 +- .../Multiple Choice/MultipleChoice.swift | 6 +- .../Semantics/Tutorial/Tasks/Steps/Code.swift | 8 +- .../Semantics/Tutorial/Tasks/Steps/Step.swift | 6 +- .../Tutorial/Tasks/Steps/Steps.swift | 4 +- .../Tutorial/Tasks/TutorialSection.swift | 10 +- .../TutorialArticle/TutorialArticle.swift | 16 +- .../SwiftDocC/DocumentationContextGroup.md | 4 +- Sources/SwiftDocC/Utility/FeatureFlags.swift | 6 +- .../Dictionary+TypedValues.swift | 4 +- .../FilesAndFolders.swift | 6 +- .../Actions/Convert/ConvertAction.swift | 18 +- .../Convert/ConvertFileWritingConsumer.swift | 12 +- .../Action/Actions/Convert/Indexer.swift | 4 +- .../Actions/EmitGeneratedCurationAction.swift | 4 +- .../ConvertAction+CommandInitialization.swift | 4 +- .../DocumentationContextConverterTests.swift | 24 +- .../Converter/RenderContextTests.swift | 4 +- .../Converter/RenderNodeCodableTests.swift | 8 +- .../TopicRenderReferenceEncoderTests.swift | 10 +- ...recatedDiagnosticsDigestWarningTests.swift | 10 +- .../Diagnostics/DiagnosticTests.swift | 4 +- .../ConvertService/ConvertServiceTests.swift | 16 +- .../DocumentationServer+DefaultTests.swift | 4 +- .../Indexing/ExternalRenderNodeTests.swift | 20 +- .../Indexing/IndexingTests.swift | 20 +- .../Indexing/NavigatorIndexTests.swift | 80 ++-- .../Indexing/RenderIndexTests.swift | 10 +- .../Infrastructure/AnchorSectionTests.swift | 30 +- .../AutoCapitalizationTests.swift | 18 +- .../AutomaticCurationTests.swift | 76 ++-- .../Infrastructure/BundleDiscoveryTests.swift | 10 +- .../DocumentationContextTests.swift | 122 ++--- .../DocumentationCuratorTests.swift | 42 +- ...=> DocumentationInputFileTypesTests.swift} | 38 +- ... DocumentationInputsIdentifierTests.swift} | 6 +- ...ift => DocumentationInputsInfoTests.swift} | 56 +-- .../ExternalPathHierarchyResolverTests.swift | 14 +- .../ExternalReferenceResolverTests.swift | 62 +-- .../Infrastructure/NodeTagsTests.swift | 10 +- .../ReferenceResolverTests.swift | 96 ++-- .../SymbolBreadcrumbTests.swift | 8 +- .../SymbolDisambiguationTests.swift | 14 +- .../SymbolGraph/SymbolGraphLoaderTests.swift | 8 +- ...SymbolGraphRelationshipsBuilderTests.swift | 56 +-- .../TestExternalReferenceResolvers.swift | 2 +- .../LinkDestinationSummaryTests.swift | 30 +- .../Model/IdentifierTests.swift | 6 +- .../Model/LineHighlighterTests.swift | 2 +- .../ParametersAndReturnValidatorTests.swift | 2 +- ...opertyListPossibleValuesSectionTests.swift | 12 +- .../Model/RenderContentMetadataTests.swift | 28 +- .../RenderHierarchyTranslatorTests.swift | 14 +- .../Model/RenderNodeDiffingBundleTests.swift | 22 +- .../Model/RenderNodeSerializationTests.swift | 32 +- .../SemaToRenderNodeMultiLanguageTests.swift | 10 +- .../Model/SemaToRenderNodeTests.swift | 426 +++++++++--------- .../Rendering/AutomaticSeeAlsoTests.swift | 30 +- .../AvailabilityRenderOrderTests.swift | 9 +- .../ConstraintsRenderSectionTests.swift | 48 +- .../DeclarationsRenderSectionTests.swift | 42 +- .../Rendering/DefaultAvailabilityTests.swift | 42 +- .../DefaultCodeListingSyntaxTests.swift | 12 +- .../Rendering/DeprecationSummaryTests.swift | 42 +- .../DocumentationContentRendererTests.swift | 4 +- .../Rendering/ExternalLinkTitleTests.swift | 4 +- .../Rendering/HeadingAnchorTests.swift | 6 +- .../MentionsRenderSectionTests.swift | 14 +- .../Rendering/PageKindTests.swift | 6 +- .../Rendering/PlatformAvailabilityTests.swift | 50 +- ...ropertyListDetailsRenderSectionTests.swift | 4 +- .../Rendering/RESTSymbolsTests.swift | 6 +- ...enderBlockContent_ThematicBreakTests.swift | 12 +- .../RenderContentCompilerTests.swift | 12 +- .../Rendering/RenderMetadataTests.swift | 22 +- ...derNodeTranslatorSymbolVariantsTests.swift | 22 +- .../Rendering/RenderNodeTranslatorTests.swift | 178 ++++---- .../SwiftDocCTests/Rendering/RoleTests.swift | 12 +- .../Rendering/SampleDownloadTests.swift | 6 +- .../Rendering/SymbolAvailabilityTests.swift | 6 +- .../Rendering/TermListTests.swift | 14 +- .../ArticleSymbolMentionsTests.swift | 2 +- .../Semantics/DoxygenTests.swift | 6 +- .../HasAtLeastOneTests.swift | 6 +- .../MarkupReferenceResolverTests.swift | 4 +- .../Semantics/MetadataTests.swift | 22 +- .../Semantics/RedirectedTests.swift | 64 +-- .../Semantics/SnippetTests.swift | 12 +- .../Semantics/VideoMediaTests.swift | 8 +- .../TestRenderNodeOutputConsumer.swift | 6 +- .../Utility/ListItemExtractorTests.swift | 12 +- .../Utility/XCTestCase+MentionedIn.swift | 5 +- .../XCTestCase+LoadingTestData.swift | 62 +-- .../ConvertActionIndexerTests.swift | 10 +- .../ConvertActionTests.swift | 8 +- .../MergeActionTests.swift | 14 +- .../SemanticAnalyzerTests.swift | 4 +- .../XCTestCase+LoadingData.swift | 10 +- 166 files changed, 1744 insertions(+), 1662 deletions(-) rename Sources/SwiftDocC/Infrastructure/{DocumentationBundleFileTypes.swift => DocumentationInputFileTypes.swift} (92%) rename Sources/SwiftDocC/Infrastructure/{DocumentationBundle+Identifier.swift => DocumentationInputs+Identifier.swift} (78%) rename Sources/SwiftDocC/Infrastructure/{DocumentationBundle.swift => DocumentationInputs.swift} (90%) rename Tests/SwiftDocCTests/Infrastructure/{DocumentationBundleFileTypesTests.swift => DocumentationInputFileTypesTests.swift} (52%) rename Tests/SwiftDocCTests/Infrastructure/{DocumentationBundleIdentifierTests.swift => DocumentationInputsIdentifierTests.swift} (91%) rename Tests/SwiftDocCTests/Infrastructure/{DocumentationBundleInfoTests.swift => DocumentationInputsInfoTests.swift} (88%) diff --git a/Sources/SwiftDocC/Converter/DocumentationContextConverter.swift b/Sources/SwiftDocC/Converter/DocumentationContextConverter.swift index 72e23665bb..79ce8dd5ad 100644 --- a/Sources/SwiftDocC/Converter/DocumentationContextConverter.swift +++ b/Sources/SwiftDocC/Converter/DocumentationContextConverter.swift @@ -20,8 +20,8 @@ public class DocumentationContextConverter { /// The context the converter uses to resolve references it finds in the documentation node's content. let context: DocumentationContext - /// The bundle that contains the content from which the documentation node originated. - let bundle: DocumentationBundle + /// The input files that contains the content from which the documentation node originated. + let inputs: DocumentationContext.Inputs /// A context that contains common pre-rendered pieces of content. let renderContext: RenderContext @@ -48,7 +48,7 @@ public class DocumentationContextConverter { /// The converter uses bundle and context to resolve references to other documentation and describe the documentation hierarchy. /// /// - Parameters: - /// - bundle: The bundle that contains the content from which the documentation node originated. + /// - inputs: The inputs files that the documentation node originated from. /// - context: The context that the converter uses to to resolve references it finds in the documentation node's content. /// - renderContext: A context that contains common pre-rendered pieces of content. /// - emitSymbolSourceFileURIs: Whether the documentation converter should include @@ -61,7 +61,7 @@ public class DocumentationContextConverter { /// - sourceRepository: The source repository where the documentation's sources are hosted. /// - symbolIdentifiersWithExpandedDocumentation: A list of symbol IDs that have version of their documentation page with more content that a renderer can link to. public init( - bundle: DocumentationBundle, + inputs: DocumentationContext.Inputs, context: DocumentationContext, renderContext: RenderContext, emitSymbolSourceFileURIs: Bool = false, @@ -69,7 +69,7 @@ public class DocumentationContextConverter { sourceRepository: SourceRepository? = nil, symbolIdentifiersWithExpandedDocumentation: [String]? = nil ) { - self.bundle = bundle + self.inputs = inputs self.context = context self.renderContext = renderContext self.shouldEmitSymbolSourceFileURIs = emitSymbolSourceFileURIs @@ -78,6 +78,27 @@ public class DocumentationContextConverter { self.symbolIdentifiersWithExpandedDocumentation = symbolIdentifiersWithExpandedDocumentation } + @available(*, deprecated, renamed: "init(inputs:context:renderContext:emitSymbolSourceFileURIs:emitSymbolAccessLevels:sourceRepository:symbolIdentifiersWithExpandedDocumentation:)", message: "Use 'init(inputs:context:renderContext:emitSymbolSourceFileURIs:emitSymbolAccessLevels:sourceRepository:symbolIdentifiersWithExpandedDocumentation:)' instead. This deprecated API will be removed after 6.3 is released") + public convenience init( + bundle: DocumentationBundle, + context: DocumentationContext, + renderContext: RenderContext, + emitSymbolSourceFileURIs: Bool = false, + emitSymbolAccessLevels: Bool = false, + sourceRepository: SourceRepository? = nil, + symbolIdentifiersWithExpandedDocumentation: [String]? = nil + ) { + self.init( + inputs: bundle, + context: context, + renderContext: renderContext, + emitSymbolSourceFileURIs: emitSymbolSourceFileURIs, + emitSymbolAccessLevels: emitSymbolAccessLevels, + sourceRepository: sourceRepository, + symbolIdentifiersWithExpandedDocumentation: symbolIdentifiersWithExpandedDocumentation + ) + } + /// Converts a documentation node to a render node. /// /// Convert a documentation node into a render node to get a self-contained, persist-able representation of a given topic's data, so you can write it to disk, send it over a network, or otherwise process it. @@ -91,7 +112,7 @@ public class DocumentationContextConverter { var translator = RenderNodeTranslator( context: context, - bundle: bundle, + inputs: inputs, identifier: node.reference, renderContext: renderContext, emitSymbolSourceFileURIs: shouldEmitSymbolSourceFileURIs, diff --git a/Sources/SwiftDocC/Converter/DocumentationNodeConverter.swift b/Sources/SwiftDocC/Converter/DocumentationNodeConverter.swift index 77804359e8..c3b17b4244 100644 --- a/Sources/SwiftDocC/Converter/DocumentationNodeConverter.swift +++ b/Sources/SwiftDocC/Converter/DocumentationNodeConverter.swift @@ -15,21 +15,26 @@ public struct DocumentationNodeConverter { /// The context the converter uses to resolve references it finds in the documentation node's content. let context: DocumentationContext - /// The bundle that contains the content from which the documentation node originated. - let bundle: DocumentationBundle + /// The input files that contains the content from which the documentation node originated. + let inputs: DocumentationContext.Inputs /// Creates a new node converter for the given bundle and context. /// /// The converter uses bundle and context to resolve references to other documentation and describe the documentation hierarchy. /// /// - Parameters: - /// - bundle: The bundle that contains the content from which the documentation node originated. + /// - inputs: The input files that contains the content from which the documentation node originated. /// - context: The context that the converter uses to to resolve references it finds in the documentation node's content. - public init(bundle: DocumentationBundle, context: DocumentationContext) { - self.bundle = bundle + public init(inputs: DocumentationContext.Inputs, context: DocumentationContext) { + self.inputs = inputs self.context = context } + @available(*, deprecated, renamed: "init(inputs:context:)", message: "Use 'init(inputs:context:)' instead. This deprecated API will be removed after 6.3 is released") + public init(bundle: DocumentationBundle, context: DocumentationContext) { + self.init(inputs: bundle, context: context) + } + /// Converts a documentation node to a render node. /// /// Convert a documentation node into a render node to get a self-contained, persistable representation of a given topic's data, so you can write it to disk, send it over a network, or otherwise process it. @@ -37,7 +42,7 @@ public struct DocumentationNodeConverter { /// - node: The documentation node to convert. /// - Returns: The render node representation of the documentation node. public func convert(_ node: DocumentationNode) -> RenderNode { - var translator = RenderNodeTranslator(context: context, bundle: bundle, identifier: node.reference) + var translator = RenderNodeTranslator(context: context, inputs: inputs, identifier: node.reference) return translator.visit(node.semantic) as! RenderNode } } diff --git a/Sources/SwiftDocC/DocumentationService/Convert/ConvertService+DataProvider.swift b/Sources/SwiftDocC/DocumentationService/Convert/ConvertService+DataProvider.swift index 75fc4b0a72..d5560f6712 100644 --- a/Sources/SwiftDocC/DocumentationService/Convert/ConvertService+DataProvider.swift +++ b/Sources/SwiftDocC/DocumentationService/Convert/ConvertService+DataProvider.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -12,7 +12,7 @@ import Foundation extension ConvertService { /// Creates a bundle and an associated in-memory data provider from the information of a given convert request - static func makeBundleAndInMemoryDataProvider(_ request: ConvertRequest) -> (bundle: DocumentationBundle, provider: InMemoryDataProvider) { + static func makeBundleAndInMemoryDataProvider(_ request: ConvertRequest) -> (inputs: DocumentationContext.Inputs, provider: InMemoryDataProvider) { var files: [URL: Data] = [:] files.reserveCapacity( request.symbolGraphs.count @@ -21,10 +21,10 @@ extension ConvertService { + request.miscResourceURLs.count ) for markupFile in request.markupFiles { - files[makeURL().appendingPathExtension(DocumentationBundleFileTypes.referenceFileExtension)] = markupFile + files[makeURL().appendingPathExtension(DocumentationInputFileTypes.referenceFileExtension)] = markupFile } for tutorialFile in request.tutorialFiles { - files[makeURL().appendingPathExtension(DocumentationBundleFileTypes.tutorialFileExtension)] = tutorialFile + files[makeURL().appendingPathExtension(DocumentationInputFileTypes.tutorialFileExtension)] = tutorialFile } let markupFileURL = Array(files.keys) @@ -37,7 +37,7 @@ extension ConvertService { } return ( - DocumentationBundle( + DocumentationContext.Inputs( info: request.bundleInfo, symbolGraphURLs: symbolGraphURLs, markupURLs: markupFileURL, diff --git a/Sources/SwiftDocC/DocumentationService/Convert/ConvertService.swift b/Sources/SwiftDocC/DocumentationService/Convert/ConvertService.swift index fc22a5c356..8858542983 100644 --- a/Sources/SwiftDocC/DocumentationService/Convert/ConvertService.swift +++ b/Sources/SwiftDocC/DocumentationService/Convert/ConvertService.swift @@ -137,7 +137,7 @@ public struct ConvertService: DocumentationService { configuration.externalDocumentationConfiguration.globalSymbolResolver = resolver } - let bundle: DocumentationBundle + let inputs: DocumentationContext.Inputs let dataProvider: any DataProvider let inputProvider = DocumentationContext.InputsProvider() @@ -149,16 +149,16 @@ public struct ConvertService: DocumentationService { additionalSymbolGraphFiles: [] ) - bundle = try inputProvider.makeInputs(contentOf: catalogURL, options: bundleDiscoveryOptions) + inputs = try inputProvider.makeInputs(contentOf: catalogURL, options: bundleDiscoveryOptions) dataProvider = FileManager.default } else { - (bundle, dataProvider) = Self.makeBundleAndInMemoryDataProvider(request) + (inputs, dataProvider) = Self.makeBundleAndInMemoryDataProvider(request) } - let context = try await DocumentationContext(bundle: bundle, dataProvider: dataProvider, configuration: configuration) + let context = try await DocumentationContext(inputs: inputs, dataProvider: dataProvider, configuration: configuration) // Precompute the render context - let renderContext = RenderContext(documentationContext: context, bundle: bundle) + let renderContext = RenderContext(documentationContext: context, inputs: inputs) let symbolIdentifiersMeetingRequirementsForExpandedDocumentation: [String]? = request.symbolIdentifiersWithExpandedDocumentation?.compactMap { identifier, expandedDocsRequirement in guard let documentationNode = context.documentationCache[identifier] else { @@ -168,7 +168,7 @@ public struct ConvertService: DocumentationService { return documentationNode.meetsExpandedDocumentationRequirements(expandedDocsRequirement) ? identifier : nil } let converter = DocumentationContextConverter( - bundle: bundle, + inputs: inputs, context: context, renderContext: renderContext, emitSymbolSourceFileURIs: request.emitSymbolSourceFileURIs, @@ -243,12 +243,12 @@ public struct ConvertService: DocumentationService { .compactMap { (value, isDocumentationExtensionContent) -> (ResolvedTopicReference, RenderReferenceStore.TopicContent)? in let (topicReference, article) = value - let bundle = context.bundle - guard bundle.id == topicReference.bundleID else { return nil } - let renderer = DocumentationContentRenderer(documentationContext: context, bundle: bundle) + let inputs = context.inputs + guard inputs.id == topicReference.bundleID else { return nil } + let renderer = DocumentationContentRenderer(documentationContext: context, inputs: inputs) let documentationNodeKind: DocumentationNode.Kind = isDocumentationExtensionContent ? .unknownSymbol : .article - let overridingDocumentationNode = DocumentationContext.documentationNodeAndTitle(for: article, kind: documentationNodeKind, in: bundle)?.node + let overridingDocumentationNode = DocumentationContext.documentationNodeAndTitle(for: article, kind: documentationNodeKind, in: inputs)?.node var dependencies = RenderReferenceDependencies() let renderReference = renderer.renderReference(for: topicReference, with: overridingDocumentationNode, dependencies: &dependencies) diff --git a/Sources/SwiftDocC/DocumentationService/Convert/Fallback Link Resolution/ConvertServiceFallbackResolver.swift b/Sources/SwiftDocC/DocumentationService/Convert/Fallback Link Resolution/ConvertServiceFallbackResolver.swift index 8ee83c262e..d96bef0fee 100644 --- a/Sources/SwiftDocC/DocumentationService/Convert/Fallback Link Resolution/ConvertServiceFallbackResolver.swift +++ b/Sources/SwiftDocC/DocumentationService/Convert/Fallback Link Resolution/ConvertServiceFallbackResolver.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2024 Apple Inc. and the Swift project authors + Copyright (c) 2024-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -26,7 +26,7 @@ protocol ConvertServiceFallbackResolver { /// The bundle identifier for the fallback resolver. /// /// The fallback resolver will only resolve links with this bundle identifier. - var bundleID: DocumentationBundle.Identifier { get } + var bundleID: DocumentationContext.Inputs.Identifier { get } // MARK: References diff --git a/Sources/SwiftDocC/DocumentationService/Models/Services/Convert/ConvertRequest.swift b/Sources/SwiftDocC/DocumentationService/Models/Services/Convert/ConvertRequest.swift index e09c124503..4e5cebe5cc 100644 --- a/Sources/SwiftDocC/DocumentationService/Models/Services/Convert/ConvertRequest.swift +++ b/Sources/SwiftDocC/DocumentationService/Models/Services/Convert/ConvertRequest.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -17,7 +17,7 @@ public struct ConvertRequest: Codable { /// /// ## See Also /// - ``DocumentationBundle/Info`` - public var bundleInfo: DocumentationBundle.Info + public var bundleInfo: DocumentationContext.Inputs.Info /// Feature flags to enable when performing this convert request. public var featureFlags: FeatureFlags @@ -116,7 +116,7 @@ public struct ConvertRequest: Codable { /// - symbolIdentifiersWithExpandedDocumentation: A dictionary of identifiers to requirements for these symbols to have expanded /// documentation available. public init( - bundleInfo: DocumentationBundle.Info, + bundleInfo: DocumentationContext.Inputs.Info, featureFlags: FeatureFlags = FeatureFlags(), externalIDsToConvert: [String]?, documentPathsToConvert: [String]? = nil, diff --git a/Sources/SwiftDocC/Infrastructure/Bundle Assets/DataAssetManager.swift b/Sources/SwiftDocC/Infrastructure/Bundle Assets/DataAssetManager.swift index c36f2542dc..86d2926fbc 100644 --- a/Sources/SwiftDocC/Infrastructure/Bundle Assets/DataAssetManager.swift +++ b/Sources/SwiftDocC/Infrastructure/Bundle Assets/DataAssetManager.swift @@ -348,10 +348,10 @@ public struct AssetReference: Hashable, Codable { public var assetName: String /// The identifier of the bundle the asset is apart of. - public let bundleID: DocumentationBundle.Identifier + public let bundleID: DocumentationContext.Inputs.Identifier /// Creates a reference from a given asset name and the bundle it is apart of. - public init(assetName: String, bundleID: DocumentationBundle.Identifier) { + public init(assetName: String, bundleID: DocumentationContext.Inputs.Identifier) { self.assetName = assetName self.bundleID = bundleID } diff --git a/Sources/SwiftDocC/Infrastructure/Context/DocumentationContext+Configuration.swift b/Sources/SwiftDocC/Infrastructure/Context/DocumentationContext+Configuration.swift index b7bcdb3293..2e5c91ddd0 100644 --- a/Sources/SwiftDocC/Infrastructure/Context/DocumentationContext+Configuration.swift +++ b/Sources/SwiftDocC/Infrastructure/Context/DocumentationContext+Configuration.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2024 Apple Inc. and the Swift project authors + Copyright (c) 2024-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -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: [DocumentationBundle.Identifier: any ExternalDocumentationSource] = [:] + public var sources: [DocumentationContext.Inputs.Identifier: any 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: (any GlobalExternalSymbolResolver)? /// A list of URLs to documentation archives that the local documentation depends on. diff --git a/Sources/SwiftDocC/Infrastructure/ConvertActionConverter.swift b/Sources/SwiftDocC/Infrastructure/ConvertActionConverter.swift index 17a5db0a70..922ffa22d2 100644 --- a/Sources/SwiftDocC/Infrastructure/ConvertActionConverter.swift +++ b/Sources/SwiftDocC/Infrastructure/ConvertActionConverter.swift @@ -24,15 +24,15 @@ package enum ConvertActionConverter { /// Converts the documentation bundle in the given context and passes its output to a given consumer. /// /// - Parameters: - /// - bundle: The documentation bundle to convert. - /// - context: The context that the bundle is a part of. + /// - inputs: The collection of inputs files that the context is created from. + /// - context: The context of documentation information to convert. /// - outputConsumer: The consumer that the conversion passes outputs of the conversion to. /// - sourceRepository: The source repository where the documentation's sources are hosted. /// - emitDigest: Whether the conversion should pass additional metadata output––such as linkable entities information, indexing information, or asset references by asset type––to the consumer. /// - documentationCoverageOptions: The level of experimental documentation coverage information that the conversion should pass to the consumer. /// - Returns: A list of problems that occurred during the conversion (excluding the problems that the context already encountered). package static func convert( - bundle: DocumentationBundle, + inputs: DocumentationContext.Inputs, context: DocumentationContext, outputConsumer: some ConvertOutputConsumer & ExternalNodeConsumer, sourceRepository: SourceRepository?, @@ -61,15 +61,15 @@ package enum ConvertActionConverter { // Precompute the render context let renderContext = signposter.withIntervalSignpost("Build RenderContext", id: signposter.makeSignpostID()) { - RenderContext(documentationContext: context, bundle: bundle) + RenderContext(documentationContext: context, inputs: inputs) } try outputConsumer.consume(renderReferenceStore: renderContext.store) // Copy images, sample files, and other static assets. - try outputConsumer.consume(assetsInBundle: bundle) + try outputConsumer.consume(assetsInInputs: inputs) let converter = DocumentationContextConverter( - bundle: bundle, + inputs: inputs, context: context, renderContext: renderContext, sourceRepository: sourceRepository @@ -109,7 +109,7 @@ package enum ConvertActionConverter { // Here we're associating the external node with the **current** bundle's bundle ID. // This is needed because nodes are only considered children if the parent and child's bundle ID match. // Otherwise, the node will be considered as a separate root node and displayed separately. - let externalRenderNode = ExternalRenderNode(externalEntity: externalLink.value, bundleIdentifier: bundle.id) + let externalRenderNode = ExternalRenderNode(externalEntity: externalLink.value, bundleIdentifier: inputs.id) try outputConsumer.consume(externalRenderNode: externalRenderNode) } @@ -192,7 +192,7 @@ package enum ConvertActionConverter { if FeatureFlags.current.isExperimentalLinkHierarchySerializationEnabled { signposter.withIntervalSignpost("Serialize link hierarchy", id: signposter.makeSignpostID()) { do { - let serializableLinkInformation = try context.linkResolver.localResolver.prepareForSerialization(bundleID: bundle.id) + let serializableLinkInformation = try context.linkResolver.localResolver.prepareForSerialization(bundleID: inputs.id) try outputConsumer.consume(linkResolutionInformation: serializableLinkInformation) if !emitDigest { @@ -225,7 +225,7 @@ package enum ConvertActionConverter { break } - try outputConsumer.consume(buildMetadata: BuildMetadata(bundleDisplayName: bundle.displayName, bundleID: bundle.id)) + try outputConsumer.consume(buildMetadata: BuildMetadata(bundleDisplayName: inputs.displayName, bundleID: inputs.id)) // Log the finalized topic graph checksum. benchmark(add: Benchmark.TopicGraphHash(context: context)) diff --git a/Sources/SwiftDocC/Infrastructure/ConvertOutputConsumer.swift b/Sources/SwiftDocC/Infrastructure/ConvertOutputConsumer.swift index f5e1ebd432..54d0efe4cd 100644 --- a/Sources/SwiftDocC/Infrastructure/ConvertOutputConsumer.swift +++ b/Sources/SwiftDocC/Infrastructure/ConvertOutputConsumer.swift @@ -23,7 +23,10 @@ public protocol ConvertOutputConsumer { /// > Warning: This method might be called concurrently. func consume(renderNode: RenderNode) throws - /// Consumes a documentation bundle with the purpose of extracting its on-disk assets. + /// Consumes a collection of input files with the purpose of extracting its on-disk assets. + func consume(assetsInInputs inputs: DocumentationContext.Inputs) throws + + @available(*, deprecated, renamed: "consume(assetsInInputs:)", message: "Use 'consume(assetsInInputs:)' instead. This deprecated API will be removed after 6.3 is released") func consume(assetsInBundle bundle: DocumentationBundle) throws /// Consumes the linkable element summaries produced during a conversion. @@ -65,6 +68,16 @@ public extension ConvertOutputConsumer { func _deprecated_consume(problems: [Problem]) throws {} } +@available(*, deprecated, message: "This deprecated API will be removed after 6.3 is released") +public extension ConvertOutputConsumer { + func consume(assetsInBundle bundle: DocumentationBundle) throws { + try consume(assetsInInputs: bundle) + } + + // This is needed so that conforming types don't break. After 6.3 is released we can remove it. + func consume(assetsInInputs inputs: DocumentationContext.Inputs) throws {} +} + // A package-internal protocol that callers can cast to when they need to call `_consume(problems:)` for backwards compatibility (until `consume(problems:)` is removed). package protocol _DeprecatedConsumeProblemsAccess { func _consume(problems: [Problem]) throws diff --git a/Sources/SwiftDocC/Infrastructure/DocumentationContext.swift b/Sources/SwiftDocC/Infrastructure/DocumentationContext.swift index cd7fca83d7..39cf2251a1 100644 --- a/Sources/SwiftDocC/Infrastructure/DocumentationContext.swift +++ b/Sources/SwiftDocC/Infrastructure/DocumentationContext.swift @@ -67,11 +67,15 @@ public class DocumentationContext { /// A class that resolves documentation links by orchestrating calls to other link resolver implementations. public var linkResolver: LinkResolver - /// The data provider that the context can use to read the contents of files that belong to ``bundle``. + /// The data provider that the context can use to read the contents of files that belong to ``inputs``. let dataProvider: any DataProvider - /// The documentation bundle that is registered with the context. - let bundle: DocumentationBundle + /// The collection of input files that the context was created from. + let inputs: DocumentationContext.Inputs + @available(*, deprecated, renamed: "inputs") + var bundle: DocumentationContext.Inputs { + inputs + } /// A collection of configuration for this context. public let configuration: Configuration @@ -129,7 +133,7 @@ public class DocumentationContext { /// references for lookup. var documentationCache = LocalCache() /// The asset managers for each documentation bundle, keyed by the bundle's identifier. - var assetManagers = [DocumentationBundle.Identifier: DataAssetManager]() + var assetManagers = [DocumentationContext.Inputs.Identifier: DataAssetManager]() /// A list of non-topic links that can be resolved. var nodeAnchorSections = [ResolvedTopicReference: AnchorSection]() @@ -197,38 +201,38 @@ public class DocumentationContext { /// Initializes a documentation context with a given `bundle`. /// /// - Parameters: - /// - bundle: The bundle to register with the context. + /// - inputs: The collection of documentation inputs files to register with the context. /// - fileManager: The file manager that the context uses to read files from the bundle. /// - diagnosticEngine: The pre-configured engine that will collect problems encountered during compilation. /// - configuration: A collection of configuration for the created context. /// - Throws: If an error is encountered while registering a documentation bundle. package init( - bundle: DocumentationBundle, + inputs: DocumentationContext.Inputs, dataProvider: any DataProvider, diagnosticEngine: DiagnosticEngine = .init(), configuration: Configuration = .init() ) async throws { - self.bundle = bundle + self.inputs = inputs self.dataProvider = dataProvider self.diagnosticEngine = diagnosticEngine self.configuration = configuration self.linkResolver = LinkResolver(dataProvider: dataProvider) - ResolvedTopicReference.enableReferenceCaching(for: bundle.id) - try register(bundle) + ResolvedTopicReference.enableReferenceCaching(for: inputs.id) + try register(inputs) } // Remove these when removing `registeredBundles` and `bundle(identifier:)`. // These exist so that internal code that need to be compatible with legacy data providers can access the bundles without deprecation warnings. @available(*, deprecated, renamed: "bundle", message: "REMOVE THIS") var _registeredBundles: [DocumentationBundle] { - [bundle] + [inputs] } @available(*, deprecated, renamed: "bundle", message: "REMOVE THIS") func _bundle(identifier: String) -> DocumentationBundle? { - assert(bundle.id.rawValue == identifier, "New code shouldn't pass unknown bundle identifiers to 'DocumentationContext.bundle(identifier:)'.") - return bundle.id.rawValue == identifier ? bundle : nil + assert(inputs.id.rawValue == identifier, "New code shouldn't pass unknown bundle identifiers to 'DocumentationContext.bundle(identifier:)'.") + return inputs.id.rawValue == identifier ? inputs : nil } /// Perform semantic analysis on a given `document` at a given `source` location and append any problems found to `problems`. @@ -236,11 +240,11 @@ public class DocumentationContext { /// - Parameters: /// - document: The document to analyze. /// - source: The location of the document. - /// - bundle: The bundle that the document belongs to. + /// - inputs: The collection of inputs files that the context was created from. /// - problems: A mutable collection of problems to update with any problem encountered during the semantic analysis. /// - Returns: The result of the semantic analysis. - private func analyze(_ document: Document, at source: URL, in bundle: DocumentationBundle, engine: DiagnosticEngine) -> Semantic? { - var analyzer = SemanticAnalyzer(source: source, bundle: bundle) + private func analyze(_ document: Document, at source: URL, in inputs: DocumentationContext.Inputs, engine: DiagnosticEngine) -> Semantic? { + var analyzer = SemanticAnalyzer(source: source, inputs: inputs) let result = analyzer.visit(document) engine.emit(analyzer.problems) return result @@ -317,7 +321,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: DocumentationBundle.Identifier) { + private func preResolveExternalLinks(references: [ResolvedTopicReference], localBundleID: DocumentationContext.Inputs.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) @@ -339,11 +343,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: DocumentationBundle.Identifier) { + private func preResolveExternalLinks(semanticObjects: [ReferencedSemanticObject], localBundleID: DocumentationContext.Inputs.Identifier) { // If there are no external resolvers added we will not resolve any links. guard !configuration.externalDocumentationConfiguration.sources.isEmpty else { return } - let collectedExternalLinks = Synchronized([DocumentationBundle.Identifier: Set]()) + let collectedExternalLinks = Synchronized([DocumentationContext.Inputs.Identifier: Set]()) semanticObjects.concurrentPerform { _, semantic in autoreleasepool { // Walk the node and extract external link references. @@ -396,7 +400,7 @@ public class DocumentationContext { /** Attempt to resolve links in curation-only documentation, converting any ``TopicReferences`` from `.unresolved` to `.resolved` where possible. */ - private func resolveLinks(curatedReferences: Set, bundle: DocumentationBundle) { + private func resolveLinks(curatedReferences: Set, inputs: DocumentationContext.Inputs) { let signpostHandle = signposter.beginInterval("Resolve links", id: signposter.makeSignpostID()) defer { signposter.endInterval("Resolve links", signpostHandle) @@ -442,7 +446,7 @@ public class DocumentationContext { return } - var resolver = ReferenceResolver(context: self, bundle: bundle, rootReference: reference, inheritanceParentReference: symbolOriginReference) + var resolver = ReferenceResolver(context: self, inputs: inputs, rootReference: reference, inheritanceParentReference: symbolOriginReference) // Update the node with the markup that contains resolved references instead of authored links. documentationNode.semantic = autoreleasepool { @@ -456,7 +460,7 @@ public class DocumentationContext { for alternateRepresentation in alternateRepresentations { let resolutionResult = resolver.resolve( alternateRepresentation.reference, - in: bundle.rootReference, + in: inputs.rootReference, range: alternateRepresentation.originalMarkup.range, severity: .warning ) @@ -553,12 +557,12 @@ public class DocumentationContext { /// - tutorialTableOfContentsResults: The list of temporary 'tutorial table-of-contents' pages. /// - tutorials: The list of temporary 'tutorial' pages. /// - tutorialArticles: The list of temporary 'tutorialArticle' pages. - /// - bundle: The bundle to resolve links against. + /// - inputs: The collection of input files that the content for the tutorial files originate from. private func resolveLinks( tutorialTableOfContents tutorialTableOfContentsResults: [SemanticResult], tutorials: [SemanticResult], tutorialArticles: [SemanticResult], - bundle: DocumentationBundle + inputs: DocumentationContext.Inputs ) { let signpostHandle = signposter.beginInterval("Resolve links", id: signposter.makeSignpostID()) defer { @@ -572,7 +576,7 @@ public class DocumentationContext { for tableOfContentsResult in tutorialTableOfContentsResults { autoreleasepool { let url = tableOfContentsResult.source - var resolver = ReferenceResolver(context: self, bundle: bundle) + var resolver = ReferenceResolver(context: self, inputs: inputs) let tableOfContents = resolver.visit(tableOfContentsResult.value) as! TutorialTableOfContents diagnosticEngine.emit(resolver.problems) @@ -644,7 +648,7 @@ public class DocumentationContext { autoreleasepool { let url = tutorialResult.source let unresolvedTutorial = tutorialResult.value - var resolver = ReferenceResolver(context: self, bundle: bundle) + var resolver = ReferenceResolver(context: self, inputs: inputs) let tutorial = resolver.visit(unresolvedTutorial) as! Tutorial diagnosticEngine.emit(resolver.problems) @@ -678,7 +682,7 @@ public class DocumentationContext { autoreleasepool { let url = articleResult.source let unresolvedTutorialArticle = articleResult.value - var resolver = ReferenceResolver(context: self, bundle: bundle) + var resolver = ReferenceResolver(context: self, inputs: inputs) let article = resolver.visit(unresolvedTutorialArticle) as! TutorialArticle diagnosticEngine.emit(resolver.problems) @@ -709,7 +713,7 @@ public class DocumentationContext { // Articles are resolved in a separate pass } - private func registerDocuments(from bundle: DocumentationBundle) throws -> ( + private func registerDocuments(from inputs: DocumentationContext.Inputs) throws -> ( tutorialTableOfContentsResults: [SemanticResult], tutorials: [SemanticResult], tutorialArticles: [SemanticResult], @@ -729,7 +733,7 @@ public class DocumentationContext { let decodeError = Synchronized<(any Error)?>(nil) // Load and analyze documents concurrently - let analyzedDocuments: [(URL, Semantic)] = bundle.markupURLs.concurrentPerform { url, results in + let analyzedDocuments: [(URL, Semantic)] = inputs.markupURLs.concurrentPerform { url, results in guard decodeError.sync({ $0 == nil }) else { return } do { @@ -744,7 +748,7 @@ public class DocumentationContext { diagnosticEngine.emit(langChecker.problems) } - guard let analyzed = analyze(document, at: url, in: bundle, engine: diagnosticEngine) else { + guard let analyzed = analyze(document, at: url, in: inputs, engine: diagnosticEngine) else { return } @@ -771,8 +775,8 @@ public class DocumentationContext { // Store the references we encounter to ensure they're unique. The file name is currently the only part of the URL considered for the topic reference, so collisions may occur. let (url, analyzed) = analyzedDocument - let path = NodeURLGenerator.pathForSemantic(analyzed, source: url, bundle: bundle) - let reference = ResolvedTopicReference(bundleID: bundle.id, path: path, sourceLanguage: .swift) + let path = NodeURLGenerator.pathForSemantic(analyzed, source: url, inputInfo: inputs.info) + let reference = ResolvedTopicReference(bundleID: inputs.id, path: path, sourceLanguage: .swift) // Since documentation extensions' filenames have no impact on the URL of pages, there is no need to enforce unique filenames for them. // At this point we consider all articles with an H1 containing link a "documentation extension." @@ -897,7 +901,7 @@ public class DocumentationContext { private func nodeWithInitializedContent( reference: ResolvedTopicReference, match foundDocumentationExtension: DocumentationContext.SemanticResult
?, - bundle: DocumentationBundle + inputs: DocumentationContext.Inputs ) -> DocumentationNode { guard var updatedNode = documentationCache[reference] else { fatalError("A topic reference that has already been resolved should always exist in the cache.") @@ -907,7 +911,7 @@ public class DocumentationContext { updatedNode.initializeSymbolContent( documentationExtension: foundDocumentationExtension?.value, engine: diagnosticEngine, - bundle: bundle + inputs: inputs ) // After merging the documentation extension into the symbol, warn about deprecation summary for non-deprecated symbols. @@ -1000,10 +1004,10 @@ public class DocumentationContext { /// Loads all graph files from a given `bundle` and merges them together while building the symbol relationships and loading any available markdown documentation for those symbols. /// - /// - Parameter bundle: The bundle to load symbol graph files from. + /// - Parameter inputs: The collection of files to load symbol graph files from. /// - Returns: A pair of the references to all loaded modules and the hierarchy of all the loaded symbol's references. private func registerSymbols( - from bundle: DocumentationBundle, + from inputs: DocumentationContext.Inputs, symbolGraphLoader: SymbolGraphLoader, documentationExtensions: [SemanticResult
] ) throws { @@ -1025,7 +1029,7 @@ public class DocumentationContext { // Build references for all symbols in all of this module's symbol graphs. let symbolReferences = signposter.withIntervalSignpost("Disambiguate references") { - linkResolver.localResolver.referencesForSymbols(in: symbolGraphLoader.unifiedGraphs, bundle: bundle, context: self) + linkResolver.localResolver.referencesForSymbols(in: symbolGraphLoader.unifiedGraphs, inputs: inputs, context: self) } // Set the index and cache storage capacity to avoid ad-hoc storage resizing. @@ -1080,7 +1084,7 @@ public class DocumentationContext { // Use the default module kind for this bundle if one was provided, // otherwise fall back to 'Framework' - let moduleKindDisplayName = bundle.info.defaultModuleKind ?? "Framework" + let moduleKindDisplayName = inputs.info.defaultModuleKind ?? "Framework" let moduleSymbol = SymbolGraph.Symbol( identifier: moduleIdentifier, names: SymbolGraph.Symbol.Names(title: moduleName, navigator: nil, subHeading: nil, prose: nil), @@ -1090,7 +1094,7 @@ public class DocumentationContext { kind: SymbolGraph.Symbol.Kind(parsedIdentifier: .module, displayName: moduleKindDisplayName), mixins: [:]) let moduleSymbolReference = SymbolReference(moduleName, interfaceLanguages: moduleInterfaceLanguages, defaultSymbol: moduleSymbol) - moduleReference = ResolvedTopicReference(symbolReference: moduleSymbolReference, moduleName: moduleName, bundle: bundle) + moduleReference = ResolvedTopicReference(symbolReference: moduleSymbolReference, moduleName: moduleName, inputs: inputs) signposter.withIntervalSignpost("Add symbols to topic graph", id: signposter.makeSignpostID()) { addSymbolsToTopicGraph(symbolGraph: unifiedSymbolGraph, url: fileURL, symbolReferences: symbolReferences, moduleReference: moduleReference) @@ -1181,7 +1185,7 @@ public class DocumentationContext { // FIXME: Resolve the link relative to the module https://github.com/swiftlang/swift-docc/issues/516 let reference = TopicReference.unresolved(.init(topicURL: url)) - switch resolve(reference, in: bundle.rootReference, fromSymbolLink: true) { + switch resolve(reference, in: inputs.rootReference, fromSymbolLink: true) { case .success(let resolved): if let existing = uncuratedDocumentationExtensions[resolved] { if symbolsWithMultipleDocumentationExtensionMatches[resolved] == nil { @@ -1242,7 +1246,7 @@ public class DocumentationContext { try GeneratedDocumentationTopics.createInheritedSymbolsAPICollections( relationships: uniqueRelationships, context: self, - bundle: bundle + inputs: inputs ) // Parse and prepare the nodes' content concurrently. @@ -1253,7 +1257,7 @@ public class DocumentationContext { let updatedNode = nodeWithInitializedContent( reference: finalReference, match: match, - bundle: bundle + inputs: inputs ) return (( @@ -1285,14 +1289,14 @@ public class DocumentationContext { } // Resolve any external references first - preResolveExternalLinks(references: Array(moduleReferences.values) + combinedSymbols.keys.compactMap({ documentationCache.reference(symbolID: $0) }), localBundleID: bundle.id) + preResolveExternalLinks(references: Array(moduleReferences.values) + combinedSymbols.keys.compactMap({ documentationCache.reference(symbolID: $0) }), localBundleID: inputs.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) for (selector, relationships) in combinedRelationshipsBySelector { // Build relationships in the completed graph - buildRelationships(relationships, selector: selector, bundle: bundle) + buildRelationships(relationships, selector: selector, bundle: inputs) // Merge into target symbols the member symbols that get rendered on the same page as target. populateOnPageMemberRelationships(from: relationships, selector: selector) } @@ -1315,7 +1319,7 @@ public class DocumentationContext { func buildRelationships( _ relationships: Set, selector: UnifiedSymbolGraph.Selector, - bundle: DocumentationBundle + bundle: DocumentationContext.Inputs ) { // Find all of the relationships which refer to an extended module. let extendedModuleRelationships = ExtendedTypeFormatTransformation.collapsedExtendedModuleRelationships(from: relationships) @@ -1647,12 +1651,12 @@ public class DocumentationContext { } } - private func registerMiscResources(from bundle: DocumentationBundle) throws { + private func registerMiscResources(from bundle: DocumentationContext.Inputs) throws { let miscResources = Set(bundle.miscResourceURLs) try assetManagers[bundle.id, default: DataAssetManager()].register(data: miscResources) } - private func registeredAssets(withExtensions extensions: Set? = nil, inContexts contexts: [DataAsset.Context] = DataAsset.Context.allCases, forBundleID bundleID: DocumentationBundle.Identifier) -> [DataAsset] { + private func registeredAssets(withExtensions extensions: Set? = nil, inContexts contexts: [DataAsset.Context] = DataAsset.Context.allCases, forBundleID bundleID: DocumentationContext.Inputs.Identifier) -> [DataAsset] { guard let resources = assetManagers[bundleID]?.storage.values else { return [] } @@ -1673,7 +1677,7 @@ public class DocumentationContext { /// /// - Parameter bundleID: 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 bundleID: DocumentationBundle.Identifier) -> [DataAsset] { + public func registeredImageAssets(for bundleID: DocumentationContext.Inputs.Identifier) -> [DataAsset] { registeredAssets(withExtensions: DocumentationContext.supportedImageExtensions, forBundleID: bundleID) } @@ -1681,7 +1685,7 @@ public class DocumentationContext { /// /// - Parameter bundleID: 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 bundleID: DocumentationBundle.Identifier) -> [DataAsset] { + public func registeredVideoAssets(for bundleID: DocumentationContext.Inputs.Identifier) -> [DataAsset] { registeredAssets(withExtensions: DocumentationContext.supportedVideoExtensions, forBundleID: bundleID) } @@ -1689,7 +1693,7 @@ public class DocumentationContext { /// /// - Parameter bundleID: 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 bundleID: DocumentationBundle.Identifier) -> [DataAsset] { + public func registeredDownloadsAssets(for bundleID: DocumentationContext.Inputs.Identifier) -> [DataAsset] { registeredAssets(inContexts: [DataAsset.Context.download], forBundleID: bundleID) } @@ -1706,7 +1710,7 @@ public class DocumentationContext { } } - private func registerRootPages(from articles: Articles, in bundle: DocumentationBundle) { + private func registerRootPages(from articles: Articles, in bundle: DocumentationContext.Inputs) { // Create a root leaf node for all root page articles for article in articles { // Create the documentation data @@ -1743,7 +1747,7 @@ public class DocumentationContext { /// - Returns: The articles that were registered, with their topic graph node updated to what's been added to the topic graph. private func registerArticles( _ articles: DocumentationContext.Articles, - in bundle: DocumentationBundle + in bundle: DocumentationContext.Inputs ) -> DocumentationContext.Articles { articles.map { article in guard let (documentation, title) = DocumentationContext.documentationNodeAndTitle( @@ -1784,7 +1788,7 @@ public class DocumentationContext { /// - Parameters: /// - articles: On input, a list of articles. If an article is used as a root it is removed from this list. /// - bundle: The bundle containing the articles. - private func synthesizeArticleOnlyRootPage(articles: inout [DocumentationContext.SemanticResult
], bundle: DocumentationBundle) { + private func synthesizeArticleOnlyRootPage(articles: inout [DocumentationContext.SemanticResult
], bundle: DocumentationContext.Inputs) { let title = bundle.displayName // An inner helper function to register a new root node from an article @@ -1865,19 +1869,19 @@ public class DocumentationContext { /// - Parameters: /// - article: The article that will be used to create the returned documentation node. /// - kind: The kind that should be used to create the returned documentation node. - /// - bundle: The documentation bundle this article belongs to. + /// - inputs: The collection of inputs files that this article belongs to. /// - Returns: A documentation node and title for the given article semantic result. static func documentationNodeAndTitle( for article: DocumentationContext.SemanticResult
, availableSourceLanguages: Set? = nil, kind: DocumentationNode.Kind, - in bundle: DocumentationBundle + in inputs: DocumentationContext.Inputs ) -> (node: DocumentationNode, title: String)? { guard let articleMarkup = article.value.markup else { return nil } - let path = NodeURLGenerator.pathForSemantic(article.value, source: article.source, bundle: bundle) + let path = NodeURLGenerator.pathForSemantic(article.value, source: article.source, inputInfo: inputs.info) // Use the languages specified by the `@SupportedLanguage` directives if present. let availableSourceLanguages = article.value @@ -1897,7 +1901,7 @@ public class DocumentationContext { let defaultSourceLanguage = defaultLanguage(in: availableSourceLanguages) let reference = ResolvedTopicReference( - bundleID: bundle.id, + bundleID: inputs.id, path: path, sourceLanguages: availableSourceLanguages // FIXME: Pages in article-only catalogs should not be inferred as "Swift" as a fallback @@ -1975,17 +1979,17 @@ public class DocumentationContext { /** Register a documentation bundle with this context. */ - private func register(_ bundle: DocumentationBundle) throws { + private func register(_ inputs: DocumentationContext.Inputs) throws { try shouldContinueRegistration() let currentFeatureFlags: FeatureFlags? - if let bundleFlags = bundle.info.featureFlags { + if let inputFileFlags = inputs.info.featureFlags { currentFeatureFlags = FeatureFlags.current - FeatureFlags.current.loadFlagsFromBundle(bundleFlags) + FeatureFlags.current.loadFlagsFromInputs(inputFileFlags) - for unknownFeatureFlag in bundleFlags.unknownFeatureFlags { + for unknownFeatureFlag in inputFileFlags.unknownFeatureFlags { let suggestions = NearMiss.bestMatches( - for: DocumentationBundle.Info.BundleFeatureFlags.CodingKeys.allCases.map({ $0.stringValue }), + for: DocumentationContext.Inputs.Info.BundleFeatureFlags.CodingKeys.allCases.map({ $0.stringValue }), against: unknownFeatureFlag) var summary: String = "Unknown feature flag in Info.plist: \(unknownFeatureFlag.singleQuoted)" if !suggestions.isEmpty { @@ -2022,7 +2026,7 @@ public class DocumentationContext { discoveryGroup.async(queue: discoveryQueue) { [unowned self] in symbolGraphLoader = SymbolGraphLoader( - bundle: bundle, + inputs: inputs, dataProvider: dataProvider, symbolGraphTransformer: configuration.convertServiceConfiguration.symbolGraphTransformer ) @@ -2034,7 +2038,7 @@ public class DocumentationContext { hierarchyBasedResolver = signposter.withIntervalSignpost("Build PathHierarchy", id: signposter.makeSignpostID()) { PathHierarchyBasedLinkResolver(pathHierarchy: PathHierarchy( symbolGraphLoader: symbolGraphLoader, - bundleName: urlReadablePath(bundle.displayName), + bundleName: urlReadablePath(inputs.displayName), knownDisambiguatedPathComponents: configuration.convertServiceConfiguration.knownDisambiguatedSymbolPathComponents )) } @@ -2050,7 +2054,7 @@ public class DocumentationContext { discoveryGroup.async(queue: discoveryQueue) { [unowned self] in do { try signposter.withIntervalSignpost("Load resources", id: signposter.makeSignpostID()) { - try self.registerMiscResources(from: bundle) + try self.registerMiscResources(from: inputs) } } catch { // Pipe the error out of the dispatch queue. @@ -2076,7 +2080,7 @@ public class DocumentationContext { discoveryGroup.async(queue: discoveryQueue) { [unowned self] in do { result = try signposter.withIntervalSignpost("Load documents", id: signposter.makeSignpostID()) { - try self.registerDocuments(from: bundle) + try self.registerDocuments(from: inputs) } } catch { // Pipe the error out of the dispatch queue. @@ -2150,7 +2154,7 @@ public class DocumentationContext { } self.linkResolver.localResolver = hierarchyBasedResolver - hierarchyBasedResolver.addMappingForRoots(bundle: bundle) + hierarchyBasedResolver.addMappingForRoots(inputs: inputs) for tutorial in tutorials { hierarchyBasedResolver.addTutorial(tutorial) } @@ -2161,8 +2165,8 @@ public class DocumentationContext { hierarchyBasedResolver.addTutorialTableOfContents(tutorialTableOfContents) } - registerRootPages(from: rootPageArticles, in: bundle) - try registerSymbols(from: bundle, symbolGraphLoader: symbolGraphLoader, documentationExtensions: documentationExtensions) + registerRootPages(from: rootPageArticles, in: inputs) + try registerSymbols(from: inputs, symbolGraphLoader: symbolGraphLoader, documentationExtensions: documentationExtensions) // We don't need to keep the loader in memory after we've registered all symbols. symbolGraphLoader = nil @@ -2172,7 +2176,7 @@ public class DocumentationContext { !otherArticles.isEmpty, !configuration.convertServiceConfiguration.allowsRegisteringArticlesWithoutTechnologyRoot { - synthesizeArticleOnlyRootPage(articles: &otherArticles, bundle: bundle) + synthesizeArticleOnlyRootPage(articles: &otherArticles, bundle: inputs) } // Keep track of the root modules registered from symbol graph files, we'll need them to automatically @@ -2187,7 +2191,7 @@ public class DocumentationContext { // Articles that will be automatically curated can be resolved but they need to be pre registered before resolving links. let rootNodeForAutomaticCuration = soleRootModuleReference.flatMap(topicGraph.nodeWithReference(_:)) if configuration.convertServiceConfiguration.allowsRegisteringArticlesWithoutTechnologyRoot || rootNodeForAutomaticCuration != nil { - otherArticles = registerArticles(otherArticles, in: bundle) + otherArticles = registerArticles(otherArticles, in: inputs) try shouldContinueRegistration() } @@ -2196,13 +2200,13 @@ public class DocumentationContext { tutorialTableOfContentsResults.map(referencedSemanticObject) + tutorials.map(referencedSemanticObject) + tutorialArticles.map(referencedSemanticObject), - localBundleID: bundle.id) + localBundleID: inputs.id) resolveLinks( tutorialTableOfContents: tutorialTableOfContentsResults, tutorials: tutorials, tutorialArticles: tutorialArticles, - bundle: bundle + inputs: inputs ) // After the resolving links in tutorial content all the local references are known and can be added to the referenceIndex for fast lookup. @@ -2215,7 +2219,7 @@ public class DocumentationContext { } try shouldContinueRegistration() - var allCuratedReferences = try crawlSymbolCuration(in: linkResolver.localResolver.topLevelSymbols(), bundle: bundle) + var allCuratedReferences = try crawlSymbolCuration(in: linkResolver.localResolver.topLevelSymbols(), inputs: inputs) // Store the list of manually curated references if doc coverage is on. if configuration.experimentalCoverageConfiguration.shouldStoreManuallyCuratedReferences { @@ -2230,13 +2234,13 @@ public class DocumentationContext { } // Crawl the rest of the symbols that haven't been crawled so far in hierarchy pre-order. - allCuratedReferences = try crawlSymbolCuration(in: automaticallyCurated.map(\.symbol), bundle: bundle, initial: allCuratedReferences) + allCuratedReferences = try crawlSymbolCuration(in: automaticallyCurated.map(\.symbol), inputs: inputs, initial: allCuratedReferences) // Automatically curate articles that haven't been manually curated // Article curation is only done automatically if there is only one root module if let rootNode = rootNodeForAutomaticCuration { let articleReferences = try autoCurateArticles(otherArticles, startingFrom: rootNode) - allCuratedReferences = try crawlSymbolCuration(in: articleReferences, bundle: bundle, initial: allCuratedReferences) + allCuratedReferences = try crawlSymbolCuration(in: articleReferences, inputs: inputs, initial: allCuratedReferences) } // Remove curation paths that have been created automatically above @@ -2254,14 +2258,14 @@ 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) - resolveLinks(curatedReferences: allCuratedReferences, bundle: bundle) + preResolveExternalLinks(references: Array(allCuratedReferences), localBundleID: inputs.id) + resolveLinks(curatedReferences: allCuratedReferences, inputs: inputs) if configuration.convertServiceConfiguration.fallbackResolver != nil { // When the ``ConvertService`` builds documentation for a single page there won't be a module or root // reference to auto-curate the page under, so the regular local link resolution code path won't visit // the single page. To ensure that links are resolved, explicitly visit all pages. - resolveLinks(curatedReferences: Set(knownPages), bundle: bundle) + resolveLinks(curatedReferences: Set(knownPages), inputs: inputs) } // We should use a read-only context during render time (rdar://65130130). @@ -2460,17 +2464,17 @@ public class DocumentationContext { /// Crawls the hierarchy of the given list of nodes, adding relationships in the topic graph for all resolvable task group references. /// - Parameters: /// - references: A list of references to crawl. - /// - bundle: A documentation bundle. + /// - inputs: A collection of input files the the crawled documentation originate from. /// - initial: A list of references to skip when crawling. /// - Returns: The references of all the symbols that were curated. @discardableResult - func crawlSymbolCuration(in references: [ResolvedTopicReference], bundle: DocumentationBundle, initial: Set = []) throws -> Set { + func crawlSymbolCuration(in references: [ResolvedTopicReference], inputs: DocumentationContext.Inputs, initial: Set = []) throws -> Set { let signpostHandle = signposter.beginInterval("Curate symbols", id: signposter.makeSignpostID()) defer { signposter.endInterval("Curate symbols", signpostHandle) } - var crawler = DocumentationCurator(in: self, bundle: bundle, initial: initial) + var crawler = DocumentationCurator(in: self, inputs: inputs, initial: initial) for reference in references { try crawler.crawlChildren( @@ -2642,7 +2646,7 @@ public class DocumentationContext { /** Unregister a documentation bundle with this context and clear any cached resources associated with it. */ - private func unregister(_ bundle: DocumentationBundle) { + private func unregister(_ bundle: DocumentationContext.Inputs) { let referencesToRemove = topicGraph.nodes.keys.filter { $0.bundleID == bundle.id } @@ -2873,7 +2877,7 @@ public class DocumentationContext { resolveAsset(named: name, bundleID: parent.bundleID, withType: type) } - func resolveAsset(named name: String, bundleID: DocumentationBundle.Identifier, withType expectedType: AssetType?) -> DataAsset? { + func resolveAsset(named name: String, bundleID: DocumentationContext.Inputs.Identifier, withType expectedType: AssetType?) -> DataAsset? { if let localAsset = assetManagers[bundleID]?.allData(named: name) { if let expectedType { guard localAsset.hasVariant(withAssetType: expectedType) else { diff --git a/Sources/SwiftDocC/Infrastructure/DocumentationCurator.swift b/Sources/SwiftDocC/Infrastructure/DocumentationCurator.swift index 1519965672..d1713d38d4 100644 --- a/Sources/SwiftDocC/Infrastructure/DocumentationCurator.swift +++ b/Sources/SwiftDocC/Infrastructure/DocumentationCurator.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -17,14 +17,14 @@ struct DocumentationCurator { /// The documentation context to crawl. private let context: DocumentationContext - /// The current bundle. - private let bundle: DocumentationBundle + /// The current collection of input files. + private let inputs: DocumentationContext.Inputs private(set) var problems = [Problem]() - init(in context: DocumentationContext, bundle: DocumentationBundle, initial: Set = []) { + init(in context: DocumentationContext, inputs: DocumentationContext.Inputs, initial: Set = []) { self.context = context - self.bundle = bundle + self.inputs = inputs self.curatedNodes = initial } @@ -80,7 +80,7 @@ struct DocumentationCurator { } // Check if the link has been externally resolved already. - if let bundleID = unresolved.topicURL.components.host.map({ DocumentationBundle.Identifier(rawValue: $0) }), + if let bundleID = unresolved.topicURL.components.host.map({ DocumentationContext.Inputs.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 @@ -99,7 +99,7 @@ struct DocumentationCurator { // - "documentation/CatalogName/ArticleName" switch path.components(separatedBy: "/").count { case 0,1: - return NodeURLGenerator.Path.article(bundleName: bundle.displayName, articleName: path).stringValue + return NodeURLGenerator.Path.article(bundleName: inputs.displayName, articleName: path).stringValue case 2: return "\(NodeURLGenerator.Path.documentationFolder)/\(path)" default: diff --git a/Sources/SwiftDocC/Infrastructure/DocumentationBundleFileTypes.swift b/Sources/SwiftDocC/Infrastructure/DocumentationInputFileTypes.swift similarity index 92% rename from Sources/SwiftDocC/Infrastructure/DocumentationBundleFileTypes.swift rename to Sources/SwiftDocC/Infrastructure/DocumentationInputFileTypes.swift index 18af82c395..8dd2a24ef3 100644 --- a/Sources/SwiftDocC/Infrastructure/DocumentationBundleFileTypes.swift +++ b/Sources/SwiftDocC/Infrastructure/DocumentationInputFileTypes.swift @@ -11,7 +11,7 @@ public import Foundation /// A collection of functions to check if a file is one of the documentation bundle files types. -public enum DocumentationBundleFileTypes { +public enum DocumentationInputFileTypes { static let referenceFileExtension = "md" /// Checks if a file is a reference documentation file. @@ -85,3 +85,7 @@ public enum DocumentationBundleFileTypes { return url.lastPathComponent == themeSettingsFileName } } + +@available(*, deprecated, renamed: "DocumentationInputFileTypes", message: "Use 'DocumentationInputFileTypes' instead. This deprecated API will be removed after 6.3 is released") +public typealias DocumentationBundleFileTypes = DocumentationInputFileTypes + diff --git a/Sources/SwiftDocC/Infrastructure/DocumentationBundle+Identifier.swift b/Sources/SwiftDocC/Infrastructure/DocumentationInputs+Identifier.swift similarity index 78% rename from Sources/SwiftDocC/Infrastructure/DocumentationBundle+Identifier.swift rename to Sources/SwiftDocC/Infrastructure/DocumentationInputs+Identifier.swift index a2afc9d699..1e978b9cd7 100644 --- a/Sources/SwiftDocC/Infrastructure/DocumentationBundle+Identifier.swift +++ b/Sources/SwiftDocC/Infrastructure/DocumentationInputs+Identifier.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2024 Apple Inc. and the Swift project authors + Copyright (c) 2024-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -10,7 +10,7 @@ import Foundation -extension DocumentationBundle { +extension DocumentationContext.Inputs { /// A stable and locally unique identifier for a collection of documentation inputs. public struct Identifier: RawRepresentable { public let rawValue: String @@ -28,32 +28,32 @@ extension DocumentationBundle { } } -extension DocumentationBundle.Identifier: Hashable {} -extension DocumentationBundle.Identifier: Sendable {} +extension DocumentationContext.Inputs.Identifier: Hashable {} +extension DocumentationContext.Inputs.Identifier: Sendable {} // Support creating an identifier from a string literal. -extension DocumentationBundle.Identifier: ExpressibleByStringLiteral { +extension DocumentationContext.Inputs.Identifier: ExpressibleByStringLiteral { public init(stringLiteral value: StringLiteralType) { self.init(rawValue: value) } } // Sort identifiers based on their raw string value. -extension DocumentationBundle.Identifier: Comparable { +extension DocumentationContext.Inputs.Identifier: Comparable { public static func < (lhs: Self, rhs: Self) -> Bool { lhs.rawValue < rhs.rawValue } } // Print as a single string value -extension DocumentationBundle.Identifier: CustomStringConvertible { +extension DocumentationContext.Inputs.Identifier: CustomStringConvertible { public var description: String { rawValue } } // Encode and decode the identifier as a single string value. -extension DocumentationBundle.Identifier: Codable { +extension DocumentationContext.Inputs.Identifier: Codable { public init(from decoder: any Decoder) throws { let container = try decoder.singleValueContainer() let rawValue = try container.decode(String.self) diff --git a/Sources/SwiftDocC/Infrastructure/DocumentationBundle.swift b/Sources/SwiftDocC/Infrastructure/DocumentationInputs.swift similarity index 90% rename from Sources/SwiftDocC/Infrastructure/DocumentationBundle.swift rename to Sources/SwiftDocC/Infrastructure/DocumentationInputs.swift index 11cc3ef426..8dfa3b708f 100644 --- a/Sources/SwiftDocC/Infrastructure/DocumentationBundle.swift +++ b/Sources/SwiftDocC/Infrastructure/DocumentationInputs.swift @@ -10,6 +10,8 @@ public import Foundation +extension DocumentationContext { + /// A collection of the build inputs for a unit of documentation. /// /// A unit of documentation may for example cover a framework, library, or tool. @@ -34,17 +36,17 @@ public import Foundation /// - ``info`` /// - ``displayName`` /// - ``identifier`` -public struct DocumentationBundle { +public struct Inputs { public enum PropertyListError: DescribedError { case invalidVersionString(String) case keyNotFound(String) public var errorDescription: String { switch self { - case .invalidVersionString(let versionString): - return "'\(versionString)' is not a valid version string" - case .keyNotFound(let name): - return "Expected key \(name.singleQuoted) not found" + case .invalidVersionString(let versionString): + return "'\(versionString)' is not a valid version string" + case .keyNotFound(let name): + return "Expected key \(name.singleQuoted) not found" } } } @@ -58,7 +60,7 @@ public struct DocumentationBundle { } /// The documentation bundle's stable and locally unique identifier. - public var id: DocumentationBundle.Identifier { + public var id: Identifier { info.id } @@ -133,16 +135,21 @@ public struct DocumentationBundle { } public private(set) var rootReference: ResolvedTopicReference - + /// Default path to resolve symbol links. public private(set) var documentationRootReference: ResolvedTopicReference - + /// Default path to resolve tutorial table-of-contents links. public var tutorialTableOfContentsContainer: ResolvedTopicReference - + /// Default path to resolve tutorial links. public var tutorialsContainerReference: ResolvedTopicReference - + /// Default path to resolve articles. public var articlesDocumentationRootReference: ResolvedTopicReference } + +} + +@available(*, deprecated, renamed: "DocumentationContext.Inputs", message: "Use 'DocumentationContext.Inputs' instead. This deprecated API will be removed after 6.3 is released") +public typealias DocumentationBundle = DocumentationContext.Inputs diff --git a/Sources/SwiftDocC/Infrastructure/External Data/OutOfProcessReferenceResolver.swift b/Sources/SwiftDocC/Infrastructure/External Data/OutOfProcessReferenceResolver.swift index 1988f8b074..07f40c4164 100644 --- a/Sources/SwiftDocC/Infrastructure/External Data/OutOfProcessReferenceResolver.swift +++ b/Sources/SwiftDocC/Infrastructure/External Data/OutOfProcessReferenceResolver.swift @@ -52,7 +52,7 @@ public class OutOfProcessReferenceResolver: ExternalDocumentationSource, GlobalE private let externalLinkResolvingClient: any ExternalLinkResolving /// The bundle identifier for the reference resolver in the other process. - public let bundleID: DocumentationBundle.Identifier + public let bundleID: DocumentationContext.Inputs.Identifier /// Creates a new reference resolver that interacts with another executable. /// @@ -89,7 +89,7 @@ public class OutOfProcessReferenceResolver: ExternalDocumentationSource, GlobalE /// - bundleID: The bundle identifier the server can resolve references for. /// - server: The server to send link resolution requests to. /// - convertRequestIdentifier: The identifier that the resolver will use for convert requests that it sends to the server. - public init(bundleID: DocumentationBundle.Identifier, server: DocumentationServer, convertRequestIdentifier: String?) throws { + public init(bundleID: DocumentationContext.Inputs.Identifier, server: DocumentationServer, convertRequestIdentifier: String?) throws { self.bundleID = bundleID self.externalLinkResolvingClient = LongRunningService( server: server, convertRequestIdentifier: convertRequestIdentifier) diff --git a/Sources/SwiftDocC/Infrastructure/Input Discovery/DocumentationInputsProvider.swift b/Sources/SwiftDocC/Infrastructure/Input Discovery/DocumentationInputsProvider.swift index 681d32dada..eb9cce2b5c 100644 --- a/Sources/SwiftDocC/Infrastructure/Input Discovery/DocumentationInputsProvider.swift +++ b/Sources/SwiftDocC/Infrastructure/Input Discovery/DocumentationInputsProvider.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2024 Apple Inc. and the Swift project authors + Copyright (c) 2024-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -72,7 +72,7 @@ extension DocumentationContext { extension DocumentationContext.InputsProvider { - private typealias FileTypes = DocumentationBundleFileTypes + private typealias FileTypes = DocumentationInputFileTypes /// A discovered documentation catalog. struct CatalogURL { @@ -130,10 +130,6 @@ extension DocumentationContext.InputsProvider { // MARK: Create from catalog -extension DocumentationContext { - package typealias Inputs = DocumentationBundle -} - extension DocumentationContext.InputsProvider { package typealias Options = BundleDiscoveryOptions @@ -243,7 +239,7 @@ extension DocumentationContext.InputsProvider { } return ( - inputs: DocumentationBundle( + inputs: DocumentationContext.Inputs( info: info, symbolGraphURLs: options.additionalSymbolGraphFiles, markupURLs: topLevelPages, diff --git a/Sources/SwiftDocC/Infrastructure/Link Resolution/LinkResolver+NavigatorIndex.swift b/Sources/SwiftDocC/Infrastructure/Link Resolution/LinkResolver+NavigatorIndex.swift index 8f0966fc79..e102a5be79 100644 --- a/Sources/SwiftDocC/Infrastructure/Link Resolution/LinkResolver+NavigatorIndex.swift +++ b/Sources/SwiftDocC/Infrastructure/Link Resolution/LinkResolver+NavigatorIndex.swift @@ -17,9 +17,9 @@ package struct ExternalRenderNode { private var externalEntity: LinkResolver.ExternalEntity /// The bundle identifier for this external node. - private var bundleIdentifier: DocumentationBundle.Identifier + private var bundleIdentifier: DocumentationContext.Inputs.Identifier - init(externalEntity: LinkResolver.ExternalEntity, bundleIdentifier: DocumentationBundle.Identifier) { + init(externalEntity: LinkResolver.ExternalEntity, bundleIdentifier: DocumentationContext.Inputs.Identifier) { self.externalEntity = externalEntity self.bundleIdentifier = bundleIdentifier } diff --git a/Sources/SwiftDocC/Infrastructure/Link Resolution/LinkResolver.swift b/Sources/SwiftDocC/Infrastructure/Link Resolution/LinkResolver.swift index 20291f286d..15c6289e5a 100644 --- a/Sources/SwiftDocC/Infrastructure/Link Resolution/LinkResolver.swift +++ b/Sources/SwiftDocC/Infrastructure/Link Resolution/LinkResolver.swift @@ -106,8 +106,8 @@ public class LinkResolver { // Check if this is a link to an external documentation source that should have previously been resolved in `DocumentationContext.preResolveExternalLinks(...)` if let bundleID = unresolvedReference.bundleID, - context.bundle.id != bundleID, - urlReadablePath(context.bundle.displayName) != bundleID.rawValue + context.inputs.id != bundleID, + urlReadablePath(context.inputs.displayName) != bundleID.rawValue { return .failure(unresolvedReference, TopicReferenceResolutionErrorInfo("No external resolver registered for '\(bundleID)'.")) } @@ -185,8 +185,8 @@ private final class FallbackResolverBasedLinkResolver { // Check if a fallback reference resolver should resolve this let referenceBundleID = unresolvedReference.bundleID ?? parent.bundleID guard let fallbackResolver = context.configuration.convertServiceConfiguration.fallbackResolver, - fallbackResolver.bundleID == context.bundle.id, - context.bundle.id == referenceBundleID || urlReadablePath(context.bundle.displayName) == referenceBundleID.rawValue + fallbackResolver.bundleID == context.inputs.id, + context.inputs.id == referenceBundleID || urlReadablePath(context.inputs.displayName) == referenceBundleID.rawValue else { return nil } @@ -204,7 +204,7 @@ private final class FallbackResolverBasedLinkResolver { ) allCandidateURLs.append(alreadyResolved.url) - let currentBundle = context.bundle + let currentBundle = context.inputs if !isCurrentlyResolvingSymbolLink { // First look up articles path allCandidateURLs.append(contentsOf: [ diff --git a/Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchy+Serialization.swift b/Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchy+Serialization.swift index d1cfe15985..0c806131e5 100644 --- a/Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchy+Serialization.swift +++ b/Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchy+Serialization.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2023 Apple Inc. and the Swift project authors + Copyright (c) 2023-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -150,7 +150,7 @@ public struct SerializableLinkResolutionInformation: Codable { // This type is public so that it can be an argument to a function in `ConvertOutputConsumer` var version: SemanticVersion - var bundleID: DocumentationBundle.Identifier + var bundleID: DocumentationContext.Inputs.Identifier var pathHierarchy: PathHierarchy.FileRepresentation // Separate storage of node data because the path hierarchy doesn't know the resolved references for articles. var nonSymbolPaths: [Int: String] @@ -160,7 +160,7 @@ extension PathHierarchyBasedLinkResolver { /// Create a file representation of the link resolver. /// /// The file representation can be decoded in later documentation builds to resolve external links to the content where the link resolver was originally created for. - func prepareForSerialization(bundleID: DocumentationBundle.Identifier) throws -> SerializableLinkResolutionInformation { + func prepareForSerialization(bundleID: DocumentationContext.Inputs.Identifier) throws -> SerializableLinkResolutionInformation { var nonSymbolPaths: [Int: String] = [:] let hierarchyFileRepresentation = PathHierarchy.FileRepresentation(pathHierarchy) { identifiers in nonSymbolPaths.reserveCapacity(identifiers.count) diff --git a/Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchyBasedLinkResolver.swift b/Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchyBasedLinkResolver.swift index 4dc85a2968..b7b9ca3f37 100644 --- a/Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchyBasedLinkResolver.swift +++ b/Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchyBasedLinkResolver.swift @@ -99,10 +99,10 @@ final class PathHierarchyBasedLinkResolver { // MARK: - Adding non-symbols /// Map the resolved identifiers to resolved topic references for a given bundle's article, tutorial, and technology root pages. - func addMappingForRoots(bundle: DocumentationBundle) { - resolvedReferenceMap[pathHierarchy.tutorialContainer.identifier] = bundle.tutorialsContainerReference - resolvedReferenceMap[pathHierarchy.articlesContainer.identifier] = bundle.articlesDocumentationRootReference - resolvedReferenceMap[pathHierarchy.tutorialOverviewContainer.identifier] = bundle.tutorialTableOfContentsContainer + func addMappingForRoots(inputs: DocumentationContext.Inputs) { + resolvedReferenceMap[pathHierarchy.tutorialContainer.identifier] = inputs.tutorialsContainerReference + resolvedReferenceMap[pathHierarchy.articlesContainer.identifier] = inputs.articlesDocumentationRootReference + resolvedReferenceMap[pathHierarchy.tutorialOverviewContainer.identifier] = inputs.tutorialTableOfContentsContainer } /// Map the resolved identifiers to resolved topic references for all symbols in the given symbol index. @@ -264,14 +264,14 @@ final class PathHierarchyBasedLinkResolver { /// /// - Parameters: /// - symbolGraph: The complete symbol graph to walk through. - /// - bundle: The bundle to use when creating symbol references. - func referencesForSymbols(in unifiedGraphs: [String: UnifiedSymbolGraph], bundle: DocumentationBundle, context: DocumentationContext) -> [SymbolGraph.Symbol.Identifier: ResolvedTopicReference] { + /// - inputs: The collection of inputs files where the symbols originated from. + func referencesForSymbols(in unifiedGraphs: [String: UnifiedSymbolGraph], inputs: DocumentationContext.Inputs, context: DocumentationContext) -> [SymbolGraph.Symbol.Identifier: ResolvedTopicReference] { let disambiguatedPaths = pathHierarchy.caseInsensitiveDisambiguatedPaths(includeDisambiguationForUnambiguousChildren: true, includeLanguage: true, allowAdvancedDisambiguation: false) var result: [SymbolGraph.Symbol.Identifier: ResolvedTopicReference] = [:] for (moduleName, symbolGraph) in unifiedGraphs { - let paths: [ResolvedTopicReference?] = Array(symbolGraph.symbols.values).concurrentMap { unifiedSymbol -> ResolvedTopicReference? in + let paths: [ResolvedTopicReference?] = Array(symbolGraph.symbols.values).concurrentMap { (unifiedSymbol: UnifiedSymbolGraph.Symbol) -> ResolvedTopicReference? in let symbol = unifiedSymbol let uniqueIdentifier = unifiedSymbol.uniqueIdentifier @@ -280,7 +280,7 @@ final class PathHierarchyBasedLinkResolver { pathComponents.count == componentsCount { let symbolReference = SymbolReference(pathComponents: pathComponents, interfaceLanguages: symbol.sourceLanguages) - return ResolvedTopicReference(symbolReference: symbolReference, moduleName: moduleName, bundle: bundle) + return ResolvedTopicReference(symbolReference: symbolReference, moduleName: moduleName, inputs: inputs) } guard let path = disambiguatedPaths[uniqueIdentifier] else { @@ -288,7 +288,7 @@ final class PathHierarchyBasedLinkResolver { } return ResolvedTopicReference( - bundleID: bundle.documentationRootReference.bundleID, + bundleID: inputs.documentationRootReference.bundleID, path: NodeURLGenerator.Path.documentationFolder + path, sourceLanguages: symbol.sourceLanguages ) diff --git a/Sources/SwiftDocC/Infrastructure/NodeURLGenerator.swift b/Sources/SwiftDocC/Infrastructure/NodeURLGenerator.swift index f58a4a32cc..4996e790ab 100644 --- a/Sources/SwiftDocC/Infrastructure/NodeURLGenerator.swift +++ b/Sources/SwiftDocC/Infrastructure/NodeURLGenerator.swift @@ -117,25 +117,30 @@ public struct NodeURLGenerator { } /// Returns a string path appropriate for the given semantic node. - public static func pathForSemantic(_ semantic: Semantic, source: URL, bundle: DocumentationBundle) -> String { + public static func pathForSemantic(_ semantic: Semantic, source: URL, inputInfo: DocumentationContext.Inputs.Info) -> String { let fileName = source.deletingPathExtension().lastPathComponent switch semantic { case is TutorialTableOfContents: return Path.tutorialTableOfContents(name: fileName).stringValue case is Tutorial, is TutorialArticle: - return Path.tutorial(bundleName: bundle.displayName, tutorialName: fileName).stringValue + return Path.tutorial(bundleName: inputInfo.displayName, tutorialName: fileName).stringValue case let article as Article: if article.metadata?.technologyRoot != nil { return Path.documentation(path: fileName).stringValue } else { - return Path.article(bundleName: bundle.displayName, articleName: fileName).stringValue + return Path.article(bundleName: inputInfo.displayName, articleName: fileName).stringValue } default: return fileName } } + @available(*, deprecated, renamed: "pathForSemantic(_:source:inputInfo:)", message: "Use 'pathForSemantic(_:source:inputInfo:)' instead. This deprecated API will be removed after 6.3 is released") + public static func pathForSemantic(_ semantic: Semantic, source: URL, bundle: DocumentationBundle) -> String { + pathForSemantic(semantic, source: source, inputInfo: bundle.info) + } + /// Returns the reference's path in a format that is safe for writing to disk. public static func fileSafeReferencePath( _ reference: ResolvedTopicReference, diff --git a/Sources/SwiftDocC/Infrastructure/Symbol Graph/GeneratedDocumentationTopics.swift b/Sources/SwiftDocC/Infrastructure/Symbol Graph/GeneratedDocumentationTopics.swift index 4ceb41fa38..19e0ede338 100644 --- a/Sources/SwiftDocC/Infrastructure/Symbol Graph/GeneratedDocumentationTopics.swift +++ b/Sources/SwiftDocC/Infrastructure/Symbol Graph/GeneratedDocumentationTopics.swift @@ -96,7 +96,7 @@ enum GeneratedDocumentationTopics { private static let defaultImplementationGroupTitle = "Default Implementations" - private static func createCollectionNode(parent: ResolvedTopicReference, title: String, identifiers: [ResolvedTopicReference], context: DocumentationContext, bundle: DocumentationBundle) throws { + private static func createCollectionNode(parent: ResolvedTopicReference, title: String, identifiers: [ResolvedTopicReference], context: DocumentationContext, inputs: DocumentationContext.Inputs) throws { let automaticCurationSourceLanguage: SourceLanguage let automaticCurationSourceLanguages: Set automaticCurationSourceLanguage = identifiers.first?.sourceLanguage ?? .swift @@ -104,7 +104,7 @@ enum GeneratedDocumentationTopics { // Create the collection topic reference let collectionReference = ResolvedTopicReference( - bundleID: bundle.id, + bundleID: inputs.id, path: NodeURLGenerator.Path.documentationCuration( parentPath: parent.path, articleName: title @@ -227,8 +227,8 @@ enum GeneratedDocumentationTopics { /// - relationships: A set of relationships to inspect. /// - symbolsURLHierarchy: A symbol graph hierarchy as created during symbol registration. /// - context: A documentation context to update. - /// - bundle: The current documentation bundle. - static func createInheritedSymbolsAPICollections(relationships: Set, context: DocumentationContext, bundle: DocumentationBundle) throws { + /// - inputs: The current collection of input files. + static func createInheritedSymbolsAPICollections(relationships: Set, context: DocumentationContext, inputs: DocumentationContext.Inputs) throws { var inheritanceIndex = InheritedSymbols() // Walk the symbol graph relationships and look for parent <-> child links that stem in a different module. @@ -258,7 +258,7 @@ enum GeneratedDocumentationTopics { for (typeReference, collections) in inheritanceIndex.implementingTypes where !collections.inheritedFromTypeName.isEmpty { for (_, collection) in collections.inheritedFromTypeName where !collection.identifiers.isEmpty { // Create a collection for the given provider type's inherited symbols - try createCollectionNode(parent: typeReference, title: collection.title, identifiers: collection.identifiers, context: context, bundle: bundle) + try createCollectionNode(parent: typeReference, title: collection.title, identifiers: collection.identifiers, context: context, inputs: inputs) } } } diff --git a/Sources/SwiftDocC/Infrastructure/Symbol Graph/ResolvedTopicReference+Symbol.swift b/Sources/SwiftDocC/Infrastructure/Symbol Graph/ResolvedTopicReference+Symbol.swift index c03c5d306f..a0e5bda8eb 100644 --- a/Sources/SwiftDocC/Infrastructure/Symbol Graph/ResolvedTopicReference+Symbol.swift +++ b/Sources/SwiftDocC/Infrastructure/Symbol Graph/ResolvedTopicReference+Symbol.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -15,13 +15,13 @@ extension ResolvedTopicReference { /// - Parameters: /// - symbolReference: A reference to a symbol. /// - moduleName: The module, to which the symbol belongs. - /// - bundle: A documentation bundle, to which the symbol belongs. - init(symbolReference: SymbolReference, moduleName: String, bundle: DocumentationBundle) { + /// - inputs: A documentation bundle, to which the symbol belongs. + init(symbolReference: SymbolReference, moduleName: String, inputs: DocumentationContext.Inputs) { let path = symbolReference.path.isEmpty ? "" : "/" + symbolReference.path self.init( - bundleID: bundle.documentationRootReference.bundleID, - path: bundle.documentationRootReference.appendingPath(moduleName + path).path, + bundleID: inputs.documentationRootReference.bundleID, + path: inputs.documentationRootReference.appendingPath(moduleName + path).path, fragment: nil, sourceLanguages: symbolReference.interfaceLanguages ) diff --git a/Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphLoader.swift b/Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphLoader.swift index 4418b6ad60..89e9803109 100644 --- a/Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphLoader.swift +++ b/Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphLoader.swift @@ -20,20 +20,20 @@ struct SymbolGraphLoader { private(set) var unifiedGraphs: [String: SymbolKit.UnifiedSymbolGraph] = [:] private(set) var graphLocations: [String: [SymbolKit.GraphCollector.GraphKind]] = [:] private let dataProvider: any DataProvider - private let bundle: DocumentationBundle + private let inputs: DocumentationContext.Inputs private let symbolGraphTransformer: ((inout SymbolGraph) -> ())? /// Creates a new symbol graph loader /// - Parameters: - /// - bundle: The documentation bundle from which to load symbol graphs. + /// - inputs: The collection of inputs files from which to load symbol graphs. /// - dataProvider: A provider that the loader uses to read symbol graph data. /// - symbolGraphTransformer: An optional closure that transforms the symbol graph after the loader decodes it. init( - bundle: DocumentationBundle, + inputs: DocumentationContext.Inputs, dataProvider: any DataProvider, symbolGraphTransformer: ((inout SymbolGraph) -> ())? = nil ) { - self.bundle = bundle + self.inputs = inputs self.dataProvider = dataProvider self.symbolGraphTransformer = symbolGraphTransformer } @@ -113,22 +113,22 @@ struct SymbolGraphLoader { // This strategy benchmarks better when we have multiple // "larger" symbol graphs. #if os(macOS) || os(iOS) - if bundle.symbolGraphURLs.filter({ !$0.lastPathComponent.contains("@") }).count > 1 { + if inputs.symbolGraphURLs.filter({ !$0.lastPathComponent.contains("@") }).count > 1 { // There are multiple main symbol graphs, better parallelize all files decoding. decodingStrategy = .concurrentlyAllFiles } #endif - let numberOfSymbolGraphs = bundle.symbolGraphURLs.count + let numberOfSymbolGraphs = inputs.symbolGraphURLs.count let decodeSignpostHandle = signposter.beginInterval("Decode symbol graphs", id: signposter.makeSignpostID(), "Decode \(numberOfSymbolGraphs) symbol graphs") switch decodingStrategy { case .concurrentlyAllFiles: // Concurrently load and decode all symbol graphs - bundle.symbolGraphURLs.concurrentPerform(block: loadGraphAtURL) + inputs.symbolGraphURLs.concurrentPerform(block: loadGraphAtURL) case .concurrentlyEachFileInBatches: // Serially load and decode all symbol graphs, each one in concurrent batches. - bundle.symbolGraphURLs.forEach(loadGraphAtURL) + inputs.symbolGraphURLs.forEach(loadGraphAtURL) } signposter.endInterval("Decode symbol graphs", decodeSignpostHandle) @@ -166,7 +166,7 @@ struct SymbolGraphLoader { var defaultUnavailablePlatforms = [PlatformName]() var defaultAvailableInformation = [DefaultAvailability.ModuleAvailability]() - if let defaultAvailabilities = bundle.info.defaultAvailability?.modules[unifiedGraph.moduleName] { + if let defaultAvailabilities = inputs.info.defaultAvailability?.modules[unifiedGraph.moduleName] { let (unavailablePlatforms, availablePlatforms) = defaultAvailabilities.categorize(where: { $0.versionInformation == .unavailable }) defaultUnavailablePlatforms = unavailablePlatforms.map(\.platformName) defaultAvailableInformation = availablePlatforms @@ -268,7 +268,7 @@ struct SymbolGraphLoader { /// this method adds them to each of the symbols in the graph. private func addDefaultAvailability(to symbolGraph: inout SymbolGraph, moduleName: String) { // Check if there are defined default availabilities for the current module - if let defaultAvailabilities = bundle.info.defaultAvailability?.modules[moduleName], + if let defaultAvailabilities = inputs.info.defaultAvailability?.modules[moduleName], let platformName = symbolGraph.module.platform.name.map(PlatformName.init) { // Prepare a default availability versions lookup for this module. diff --git a/Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphRelationshipsBuilder.swift b/Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphRelationshipsBuilder.swift index 836b84775d..24739d4efa 100644 --- a/Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphRelationshipsBuilder.swift +++ b/Sources/SwiftDocC/Infrastructure/Symbol Graph/SymbolGraphRelationshipsBuilder.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -52,14 +52,14 @@ struct SymbolGraphRelationshipsBuilder { /// - Parameters: /// - edge: A symbol graph relationship with a source and a target. /// - selector: The symbol graph selector in which the relationship is relevant. - /// - bundle: A documentation bundle. + /// - inputs: The collection of inputs files that the context was created from. /// - context: A documentation context. /// - localCache: A cache of local documentation content. /// - engine: A diagnostic collecting engine. static func addImplementationRelationship( edge: SymbolGraph.Relationship, selector: UnifiedSymbolGraph.Selector, - in bundle: DocumentationBundle, + in inputs: DocumentationContext.Inputs, context: DocumentationContext, localCache: DocumentationContext.LocalCache, engine: DiagnosticEngine @@ -83,7 +83,7 @@ struct SymbolGraphRelationshipsBuilder { ?? implementorNode.reference.sourceLanguage let symbolReference = SymbolReference(edge.target, interfaceLanguage: language, symbol: localCache[edge.target]?.symbol) - guard let unresolved = UnresolvedTopicReference(symbolReference: symbolReference, bundle: bundle) else { + guard let unresolved = UnresolvedTopicReference(symbolReference: symbolReference, inputs: inputs) else { // The symbol reference format is invalid. assertionFailure(AssertionMessages.invalidSymbolReference(symbolReference)) return @@ -137,14 +137,14 @@ struct SymbolGraphRelationshipsBuilder { /// - Parameters: /// - edge: A symbol-graph relationship with a source and a target. /// - selector: The symbol graph selector in which the relationship is relevant. - /// - bundle: A documentation bundle. + /// - inputs: The collection of inputs files that the context was created from. /// - localCache: A cache of local documentation content. /// - externalCache: A cache of external documentation content. /// - engine: A diagnostic collecting engine. static func addConformanceRelationship( edge: SymbolGraph.Relationship, selector: UnifiedSymbolGraph.Selector, - in bundle: DocumentationBundle, + in inputs: DocumentationContext.Inputs, localCache: DocumentationContext.LocalCache, externalCache: DocumentationContext.ExternalCache, engine: DiagnosticEngine @@ -173,7 +173,7 @@ struct SymbolGraphRelationshipsBuilder { ?? conformingNode.reference.sourceLanguage let symbolReference = SymbolReference(edge.target, interfaceLanguage: language, symbol: localCache[edge.target]?.symbol) - guard let unresolved = UnresolvedTopicReference(symbolReference: symbolReference, bundle: bundle) else { + guard let unresolved = UnresolvedTopicReference(symbolReference: symbolReference, inputs: inputs) else { // The symbol reference format is invalid. assertionFailure(AssertionMessages.invalidSymbolReference(symbolReference)) return @@ -226,14 +226,14 @@ struct SymbolGraphRelationshipsBuilder { /// - Parameters: /// - edge: A symbol graph relationship with a source and a target. /// - selector: The symbol graph selector in which the relationship is relevant. - /// - bundle: A documentation bundle. + /// - inputs: The collection of inputs files that the context was created from. /// - localCache: A cache of local documentation content. /// - externalCache: A cache of external documentation content. /// - engine: A diagnostic collecting engine. static func addInheritanceRelationship( edge: SymbolGraph.Relationship, selector: UnifiedSymbolGraph.Selector, - in bundle: DocumentationBundle, + in inputs: DocumentationContext.Inputs, localCache: DocumentationContext.LocalCache, externalCache: DocumentationContext.ExternalCache, engine: DiagnosticEngine @@ -260,7 +260,7 @@ struct SymbolGraphRelationshipsBuilder { let language = childNode.reference.sourceLanguage let symbolReference = SymbolReference(edge.target, interfaceLanguage: language, symbol: nil) - guard let unresolved = UnresolvedTopicReference(symbolReference: symbolReference, bundle: bundle) else { + guard let unresolved = UnresolvedTopicReference(symbolReference: symbolReference, inputs: inputs) else { // The symbol reference format is invalid. assertionFailure(AssertionMessages.invalidSymbolReference(symbolReference)) return diff --git a/Sources/SwiftDocC/Infrastructure/Symbol Graph/UnresolvedTopicReference+Symbol.swift b/Sources/SwiftDocC/Infrastructure/Symbol Graph/UnresolvedTopicReference+Symbol.swift index 42cacab44e..5d49a41e37 100644 --- a/Sources/SwiftDocC/Infrastructure/Symbol Graph/UnresolvedTopicReference+Symbol.swift +++ b/Sources/SwiftDocC/Infrastructure/Symbol Graph/UnresolvedTopicReference+Symbol.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -14,11 +14,11 @@ extension UnresolvedTopicReference { /// Creates an unresolved reference out of a symbol reference. /// - Parameters: /// - symbolReference: A reference to a symbol. - /// - bundle: A documentation bundle. - init?(symbolReference: SymbolReference, bundle: DocumentationBundle) { + /// - inputs: A collection of inputs files that the symbol is from. + init?(symbolReference: SymbolReference, inputs: DocumentationContext.Inputs) { guard var components = URLComponents(string: symbolReference.path) else { return nil } components.scheme = ResolvedTopicReference.urlScheme - components.host = bundle.id.rawValue + components.host = inputs.id.rawValue if !components.path.hasPrefix("/") { components.path.insert("/", at: components.path.startIndex) } diff --git a/Sources/SwiftDocC/Infrastructure/Topic Graph/AutomaticCuration.swift b/Sources/SwiftDocC/Infrastructure/Topic Graph/AutomaticCuration.swift index be5516727a..a10083e065 100644 --- a/Sources/SwiftDocC/Infrastructure/Topic Graph/AutomaticCuration.swift +++ b/Sources/SwiftDocC/Infrastructure/Topic Graph/AutomaticCuration.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -148,14 +148,14 @@ public struct AutomaticCuration { /// - Parameters: /// - node: A node for which to generate a See Also group. /// - context: A documentation context. - /// - bundle: A documentation bundle. + /// - inputs: The collection of input files that the context is created from. /// - Returns: A group title and the group's references or links. /// `nil` if the method can't find any relevant links to automatically generate a See Also content. static func seeAlso( for node: DocumentationNode, withTraits variantsTraits: Set, context: DocumentationContext, - bundle: DocumentationBundle, + inputs: DocumentationContext.Inputs, renderContext: RenderContext?, renderer: DocumentationContentRenderer ) -> TaskGroup? { diff --git a/Sources/SwiftDocC/Infrastructure/Workspace/DefaultAvailability.swift b/Sources/SwiftDocC/Infrastructure/Workspace/DefaultAvailability.swift index 4f4bcb49d7..d7d40d58c3 100644 --- a/Sources/SwiftDocC/Infrastructure/Workspace/DefaultAvailability.swift +++ b/Sources/SwiftDocC/Infrastructure/Workspace/DefaultAvailability.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -107,7 +107,7 @@ public struct DefaultAvailability: Codable, Equatable { // semantic version. if let introducedVersion { guard let version = Version(versionString: introducedVersion), (2...3).contains(version.count) else { - throw DocumentationBundle.PropertyListError.invalidVersionString(introducedVersion) + throw DocumentationContext.Inputs.PropertyListError.invalidVersionString(introducedVersion) } } } diff --git a/Sources/SwiftDocC/Infrastructure/Workspace/DocumentationBundle+Info.swift b/Sources/SwiftDocC/Infrastructure/Workspace/DocumentationBundle+Info.swift index 28d4490c80..92049bb7bd 100644 --- a/Sources/SwiftDocC/Infrastructure/Workspace/DocumentationBundle+Info.swift +++ b/Sources/SwiftDocC/Infrastructure/Workspace/DocumentationBundle+Info.swift @@ -10,7 +10,7 @@ public import Foundation -extension DocumentationBundle { +extension DocumentationContext.Inputs { /// Information about a documentation bundle that's unrelated to its documentation content. /// /// This information is meant to be decoded from the bundle's Info.plist file. @@ -19,7 +19,7 @@ extension DocumentationBundle { public var displayName: String /// The unique identifier of the bundle. - public var id: DocumentationBundle.Identifier + public var id: DocumentationContext.Inputs.Identifier /// The default language identifier for code listings in the bundle. public var defaultCodeListingLanguage: String? @@ -85,7 +85,7 @@ extension DocumentationBundle { /// - defaultModuleKind: The default kind for the various modules in the bundle. public init( displayName: String, - id: DocumentationBundle.Identifier, + id: DocumentationContext.Inputs.Identifier, defaultCodeListingLanguage: String?, defaultAvailability: DefaultAvailability?, defaultModuleKind: String? @@ -120,7 +120,7 @@ extension DocumentationBundle { do { self = try propertyListDecoder.decode( - DocumentationBundle.Info.self, + DocumentationContext.Inputs.Info.self, from: infoPlist ) } catch DecodingError.dataCorrupted(let context) { @@ -148,7 +148,7 @@ extension DocumentationBundle { } private init( - with values: KeyedDecodingContainer?, + with values: KeyedDecodingContainer?, bundleDiscoveryOptions: BundleDiscoveryOptions?, derivedDisplayName: String? ) throws { @@ -179,7 +179,7 @@ extension DocumentationBundle { } else if let values { return try values.decode(T.self, forKey: key) } else { - throw DocumentationBundle.PropertyListError.keyNotFound(key.rawValue) + throw DocumentationContext.Inputs.PropertyListError.keyNotFound(key.rawValue) } } @@ -232,7 +232,7 @@ extension DocumentationBundle { init( displayName: String, - id: DocumentationBundle.Identifier, + id: DocumentationContext.Inputs.Identifier, defaultCodeListingLanguage: String? = nil, defaultModuleKind: String? = nil, defaultAvailability: DefaultAvailability? = nil, @@ -274,7 +274,7 @@ extension BundleDiscoveryOptions { // This ensures that when new coding keys are added, the compiler will enforce // that we handle them here as well. - let fallbacks = DocumentationBundle.Info.CodingKeys.allCases.compactMap { key -> (String, Any)? in + let fallbacks = DocumentationContext.Inputs.Info.CodingKeys.allCases.compactMap { key -> (String, Any)? in let value: Any? switch key { diff --git a/Sources/SwiftDocC/Infrastructure/Workspace/DocumentationWorkspaceDataProvider.swift b/Sources/SwiftDocC/Infrastructure/Workspace/DocumentationWorkspaceDataProvider.swift index e068262975..9a5862d123 100644 --- a/Sources/SwiftDocC/Infrastructure/Workspace/DocumentationWorkspaceDataProvider.swift +++ b/Sources/SwiftDocC/Infrastructure/Workspace/DocumentationWorkspaceDataProvider.swift @@ -44,7 +44,7 @@ public struct BundleDiscoveryOptions { /// - fallbackInfo: Fallback documentation bundle information to use if any discovered bundles are missing an Info.plist. /// - additionalSymbolGraphFiles: Additional symbol graph files to augment any discovered bundles. public init( - fallbackInfo: DocumentationBundle.Info, + fallbackInfo: DocumentationContext.Inputs.Info, additionalSymbolGraphFiles: [URL] = [] ) throws { // Use JSONEncoder to dynamically create the Info.plist fallback @@ -55,7 +55,7 @@ public struct BundleDiscoveryOptions { let serializedFallbackInfo = try JSONSerialization.jsonObject(with: data) guard let fallbackInfoDictionary = serializedFallbackInfo as? [String: Any] else { - throw DocumentationBundle.Info.Error.wrongType( + throw DocumentationContext.Inputs.Info.Error.wrongType( expected: [String: Any].Type.self, actual: type(of: serializedFallbackInfo) ) diff --git a/Sources/SwiftDocC/Infrastructure/Workspace/FeatureFlags+Info.swift b/Sources/SwiftDocC/Infrastructure/Workspace/FeatureFlags+Info.swift index dd62465ddd..4d8856b956 100644 --- a/Sources/SwiftDocC/Infrastructure/Workspace/FeatureFlags+Info.swift +++ b/Sources/SwiftDocC/Infrastructure/Workspace/FeatureFlags+Info.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2024 Apple Inc. and the Swift project authors + Copyright (c) 2024-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -10,7 +10,7 @@ import Foundation -extension DocumentationBundle.Info { +extension DocumentationContext.Inputs.Info { /// A collection of feature flags that can be enabled from a bundle's Info.plist. /// /// This is a subset of flags from ``FeatureFlags`` that can influence how a documentation diff --git a/Sources/SwiftDocC/LinkTargets/LinkDestinationSummary.swift b/Sources/SwiftDocC/LinkTargets/LinkDestinationSummary.swift index 8c6112dbb1..884afe6f54 100644 --- a/Sources/SwiftDocC/LinkTargets/LinkDestinationSummary.swift +++ b/Sources/SwiftDocC/LinkTargets/LinkDestinationSummary.swift @@ -311,15 +311,15 @@ public extension DocumentationNode { renderNode: RenderNode, includeTaskGroups: Bool = true ) -> [LinkDestinationSummary] { - let bundle = context.bundle - guard bundle.id == reference.bundleID else { + let inputs = context.inputs + guard inputs.id == reference.bundleID else { // Don't return anything for external references that don't have a bundle in the context. return [] } - let urlGenerator = PresentationURLGenerator(context: context, baseURL: bundle.baseURL) + let urlGenerator = PresentationURLGenerator(context: context, baseURL: inputs.baseURL) let relativePresentationURL = urlGenerator.presentationURLForReference(reference).withoutHostAndPortAndScheme() - var compiler = RenderContentCompiler(context: context, bundle: bundle, identifier: reference) + var compiler = RenderContentCompiler(context: context, inputs: inputs, identifier: reference) let platforms = renderNode.metadata.platforms diff --git a/Sources/SwiftDocC/Model/BuildMetadata.swift b/Sources/SwiftDocC/Model/BuildMetadata.swift index 39a83aa468..e0db538e7f 100644 --- a/Sources/SwiftDocC/Model/BuildMetadata.swift +++ b/Sources/SwiftDocC/Model/BuildMetadata.swift @@ -24,14 +24,14 @@ public struct BuildMetadata: Codable { public var bundleDisplayName: String /// The bundle identifier of the documentation bundle that DocC built. - public let bundleID: DocumentationBundle.Identifier + public let bundleID: DocumentationContext.Inputs.Identifier /// Creates a build metadata value for a documentation bundle built by DocC. /// /// - Parameters: /// - bundleDisplayName: The display name of the documentation bundle. /// - bundleID: The bundle identifier of the documentation bundle. - public init(bundleDisplayName: String, bundleID: DocumentationBundle.Identifier) { + public init(bundleDisplayName: String, bundleID: DocumentationContext.Inputs.Identifier) { self.bundleDisplayName = bundleDisplayName self.bundleID = bundleID } diff --git a/Sources/SwiftDocC/Model/DocumentationNode.swift b/Sources/SwiftDocC/Model/DocumentationNode.swift index 803ddb7761..da4bc6751f 100644 --- a/Sources/SwiftDocC/Model/DocumentationNode.swift +++ b/Sources/SwiftDocC/Model/DocumentationNode.swift @@ -332,14 +332,14 @@ public struct DocumentationNode { mutating func initializeSymbolContent( documentationExtension: Article?, engine: DiagnosticEngine, - bundle: DocumentationBundle + inputs: DocumentationContext.Inputs ) { precondition(unifiedSymbol != nil && symbol != nil, "You can only call initializeSymbolContent() on a symbol node.") let (markup, docChunks, metadataFromDocumentationComment) = Self.contentFrom( documentedSymbol: unifiedSymbol?.documentedSymbol, documentationExtension: documentationExtension, - bundle: bundle, + inputs: inputs, engine: engine ) @@ -500,7 +500,7 @@ public struct DocumentationNode { static func contentFrom( documentedSymbol: SymbolGraph.Symbol?, documentationExtension: Article?, - bundle: DocumentationBundle? = nil, + inputs: DocumentationContext.Inputs? = nil, engine: DiagnosticEngine ) -> ( markup: any Markup, @@ -543,14 +543,14 @@ public struct DocumentationNode { var problems = [Problem]() - if let bundle { + if let inputs { metadata = DirectiveParser() .parseSingleDirective( Metadata.self, from: &docCommentMarkupElements, parentType: Symbol.self, source: docCommentLocation?.url, - bundle: bundle, + inputs: inputs, problems: &problems ) diff --git a/Sources/SwiftDocC/Model/Identifier.swift b/Sources/SwiftDocC/Model/Identifier.swift index 469af2f4ca..ece027d9d3 100644 --- a/Sources/SwiftDocC/Model/Identifier.swift +++ b/Sources/SwiftDocC/Model/Identifier.swift @@ -140,7 +140,7 @@ extension TopicReferenceResolutionErrorInfo { /// > Important: This type has copy-on-write semantics and wraps an underlying class to store /// > its data. public struct ResolvedTopicReference: Hashable, Codable, Equatable, CustomStringConvertible { - typealias ReferenceBundleIdentifier = DocumentationBundle.Identifier + typealias ReferenceBundleIdentifier = DocumentationContext.Inputs.Identifier private struct ReferenceKey: Hashable { var path: String var fragment: String? @@ -177,7 +177,7 @@ public struct ResolvedTopicReference: Hashable, Codable, Equatable, CustomString let _storage: Storage /// The identifier of the bundle that owns this documentation topic. - public var bundleID: DocumentationBundle.Identifier { + public var bundleID: DocumentationContext.Inputs.Identifier { _storage.bundleID } @@ -207,11 +207,11 @@ public struct ResolvedTopicReference: Hashable, Codable, Equatable, CustomString } /// - Note: The `path` parameter is escaped to a path readable string. - public init(bundleID: DocumentationBundle.Identifier, path: String, fragment: String? = nil, sourceLanguage: SourceLanguage) { + public init(bundleID: DocumentationContext.Inputs.Identifier, path: String, fragment: String? = nil, sourceLanguage: SourceLanguage) { self.init(bundleID: bundleID, path: path, fragment: fragment, sourceLanguages: [sourceLanguage]) } - public init(bundleID: DocumentationBundle.Identifier, path: String, fragment: String? = nil, sourceLanguages: Set) { + public init(bundleID: DocumentationContext.Inputs.Identifier, path: String, fragment: String? = nil, sourceLanguages: Set) { self.init( bundleID: bundleID, urlReadablePath: urlReadablePath(path), @@ -220,7 +220,7 @@ public struct ResolvedTopicReference: Hashable, Codable, Equatable, CustomString ) } - private init(bundleID: DocumentationBundle.Identifier, urlReadablePath: String, urlReadableFragment: String? = nil, sourceLanguages: Set) { + private init(bundleID: DocumentationContext.Inputs.Identifier, urlReadablePath: String, urlReadableFragment: String? = nil, sourceLanguages: Set) { precondition(!sourceLanguages.isEmpty, "ResolvedTopicReference.sourceLanguages cannot be empty") // Check for a cached instance of the reference let key = ReferenceKey(path: urlReadablePath, fragment: urlReadableFragment, sourceLanguages: sourceLanguages) @@ -440,7 +440,7 @@ public struct ResolvedTopicReference: Hashable, Codable, Equatable, CustomString /// /// This is a reference type which allows ``ResolvedTopicReference`` to have copy-on-write behavior. class Storage: Hashable { - let bundleID: DocumentationBundle.Identifier + let bundleID: DocumentationContext.Inputs.Identifier let path: String let fragment: String? let sourceLanguages: Set @@ -452,7 +452,7 @@ public struct ResolvedTopicReference: Hashable, Codable, Equatable, CustomString let absoluteString: String init( - bundleID: DocumentationBundle.Identifier, + bundleID: DocumentationContext.Inputs.Identifier, path: String, fragment: String? = nil, sourceLanguages: Set @@ -529,7 +529,7 @@ public struct UnresolvedTopicReference: Hashable, CustomStringConvertible { public let topicURL: ValidatedURL /// The bundle identifier, if one was provided in the host name component of the original URL. - public var bundleID: DocumentationBundle.Identifier? { + public var bundleID: DocumentationContext.Inputs.Identifier? { topicURL.components.host.map { .init(rawValue: $0) } } @@ -590,7 +590,7 @@ public struct UnresolvedTopicReference: Hashable, CustomStringConvertible { /// A reference to an auxiliary resource such as an image. public struct ResourceReference: Hashable { /// The documentation bundle identifier for the bundle in which this resource resides. - public let bundleID: DocumentationBundle.Identifier + public let bundleID: DocumentationContext.Inputs.Identifier /// The path of the resource local to its bundle. public let path: String @@ -599,7 +599,7 @@ public struct ResourceReference: Hashable { /// - Parameters: /// - bundleID: The documentation bundle identifier for the bundle in which this resource resides. /// - path: The path of the resource local to its bundle. - init(bundleID: DocumentationBundle.Identifier, path: String) { + init(bundleID: DocumentationContext.Inputs.Identifier, path: String) { self.bundleID = bundleID self.path = path.removingPercentEncoding ?? path } diff --git a/Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift b/Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift index 2ad9f43a8b..758c16842c 100644 --- a/Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift +++ b/Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift @@ -48,17 +48,22 @@ extension RenderReferenceDependencies: Codable { public class DocumentationContentRenderer { let documentationContext: DocumentationContext - let bundle: DocumentationBundle + let inputs: DocumentationContext.Inputs let urlGenerator: PresentationURLGenerator - /// Creates a new content renderer for the given documentation context and bundle. + /// Creates a new content renderer for the given documentation context and inputs. /// - Parameters: /// - documentationContext: A documentation context. - /// - bundle: A documentation bundle. - public init(documentationContext: DocumentationContext, bundle: DocumentationBundle) { + /// - inputs: A collection of inputs files that the context was created from. + public init(documentationContext: DocumentationContext, inputs: DocumentationContext.Inputs) { self.documentationContext = documentationContext - self.bundle = bundle - self.urlGenerator = PresentationURLGenerator(context: documentationContext, baseURL: bundle.baseURL) + self.inputs = inputs + self.urlGenerator = PresentationURLGenerator(context: documentationContext, baseURL: inputs.baseURL) + } + + @available(*, deprecated, renamed: "init(documentationContext:inputs:)", message: "Use 'init(documentationContext:inputs:)' instead. This deprecated API will be removed after 6.3 is released") + public convenience init(documentationContext: DocumentationContext, bundle: DocumentationBundle) { + self.init(documentationContext: documentationContext, inputs: bundle) } /// For symbol nodes, returns the declaration render section if any. @@ -324,7 +329,7 @@ public class DocumentationContentRenderer { // Topic render references require the URLs to be relative, even if they're external. let presentationURL = urlGenerator.presentationURLForReference(reference) - var contentCompiler = RenderContentCompiler(context: documentationContext, bundle: bundle, identifier: reference) + var contentCompiler = RenderContentCompiler(context: documentationContext, inputs: inputs, identifier: reference) let abstractContent: VariantCollection<[RenderInlineContent]> var abstractedNode = node @@ -516,7 +521,7 @@ public class DocumentationContentRenderer { } let supportedLanguages = group.directives[SupportedLanguage.directiveName]?.compactMap { - SupportedLanguage(from: $0, source: nil, for: bundle)?.language + SupportedLanguage(from: $0, source: nil, for: inputs)?.language } return ReferenceGroup( diff --git a/Sources/SwiftDocC/Model/Rendering/LinkTitleResolver.swift b/Sources/SwiftDocC/Model/Rendering/LinkTitleResolver.swift index 73f85a43f4..2aceb26ecf 100644 --- a/Sources/SwiftDocC/Model/Rendering/LinkTitleResolver.swift +++ b/Sources/SwiftDocC/Model/Rendering/LinkTitleResolver.swift @@ -31,11 +31,11 @@ struct LinkTitleResolver { var problems = [Problem]() switch directive.name { case Tutorial.directiveName: - if let tutorial = Tutorial(from: directive, source: source, for: context.bundle, problems: &problems) { + if let tutorial = Tutorial(from: directive, source: source, for: context.inputs, problems: &problems) { return .init(defaultVariantValue: tutorial.intro.title) } case TutorialTableOfContents.directiveName: - if let overview = TutorialTableOfContents(from: directive, source: source, for: context.bundle, problems: &problems) { + if let overview = TutorialTableOfContents(from: directive, source: source, for: context.inputs, problems: &problems) { return .init(defaultVariantValue: overview.name) } default: break diff --git a/Sources/SwiftDocC/Model/Rendering/Navigation Tree/RenderHierarchyTranslator.swift b/Sources/SwiftDocC/Model/Rendering/Navigation Tree/RenderHierarchyTranslator.swift index 25c6708333..bae8c408c3 100644 --- a/Sources/SwiftDocC/Model/Rendering/Navigation Tree/RenderHierarchyTranslator.swift +++ b/Sources/SwiftDocC/Model/Rendering/Navigation Tree/RenderHierarchyTranslator.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -13,7 +13,7 @@ import Foundation /// A hierarchy translator that converts a part of the topic graph into a hierarchy tree. struct RenderHierarchyTranslator { var context: DocumentationContext - var bundle: DocumentationBundle + var inputs: DocumentationContext.Inputs var collectedTopicReferences = Set() var linkReferences = [String: LinkReference]() @@ -21,10 +21,10 @@ struct RenderHierarchyTranslator { /// Creates a new translator for the given bundle in the given context. /// - Parameters: /// - context: The documentation context for the conversion. - /// - bundle: The documentation bundle for the conversion. - init(context: DocumentationContext, bundle: DocumentationBundle) { + /// - inputs: The collection of inputs files that the content originated from. + init(context: DocumentationContext, inputs: DocumentationContext.Inputs) { self.context = context - self.bundle = bundle + self.inputs = inputs } static let assessmentsAnchor = urlReadableFragment(TutorialAssessmentsRenderSection.title) @@ -164,7 +164,7 @@ struct RenderHierarchyTranslator { let assessmentReference = ResolvedTopicReference(bundleID: tutorialReference.bundleID, path: tutorialReference.path, fragment: RenderHierarchyTranslator.assessmentsAnchor, sourceLanguage: .swift) renderHierarchyTutorial.landmarks.append(RenderHierarchyLandmark(reference: RenderReferenceIdentifier(assessmentReference.absoluteString), kind: .assessment)) - let urlGenerator = PresentationURLGenerator(context: context, baseURL: bundle.baseURL) + let urlGenerator = PresentationURLGenerator(context: context, baseURL: inputs.baseURL) let assessmentLinkReference = LinkReference( identifier: RenderReferenceIdentifier(assessmentReference.absoluteString), title: "Check Your Understanding", diff --git a/Sources/SwiftDocC/Model/Rendering/RenderContentCompiler.swift b/Sources/SwiftDocC/Model/Rendering/RenderContentCompiler.swift index 58fabccede..a2764a715b 100644 --- a/Sources/SwiftDocC/Model/Rendering/RenderContentCompiler.swift +++ b/Sources/SwiftDocC/Model/Rendering/RenderContentCompiler.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -20,7 +20,7 @@ extension RenderInlineContent: RenderContent {} struct RenderContentCompiler: MarkupVisitor { var context: DocumentationContext - var bundle: DocumentationBundle + var inputs: DocumentationContext.Inputs var identifier: ResolvedTopicReference var imageReferences: [String: ImageReference] = [:] var videoReferences: [String: VideoReference] = [:] @@ -28,9 +28,9 @@ struct RenderContentCompiler: MarkupVisitor { var collectedTopicReferences = GroupedSequence { $0.absoluteString } var linkReferences: [String: LinkReference] = [:] - init(context: DocumentationContext, bundle: DocumentationBundle, identifier: ResolvedTopicReference) { + init(context: DocumentationContext, inputs: DocumentationContext.Inputs, identifier: ResolvedTopicReference) { self.context = context - self.bundle = bundle + self.inputs = inputs self.identifier = identifier } @@ -47,7 +47,7 @@ struct RenderContentCompiler: MarkupVisitor { mutating func visitCodeBlock(_ codeBlock: CodeBlock) -> [any RenderContent] { // Default to the bundle's code listing syntax if one is not explicitly declared in the code block. - return [RenderBlockContent.codeListing(.init(syntax: codeBlock.language ?? bundle.info.defaultCodeListingLanguage, code: codeBlock.code.splitByNewlines, metadata: nil))] + return [RenderBlockContent.codeListing(.init(syntax: codeBlock.language ?? inputs.info.defaultCodeListingLanguage, code: codeBlock.code.splitByNewlines, metadata: nil))] } mutating func visitHeading(_ heading: Heading) -> [any RenderContent] { diff --git a/Sources/SwiftDocC/Model/Rendering/RenderContentConvertible.swift b/Sources/SwiftDocC/Model/Rendering/RenderContentConvertible.swift index 6e7325c800..48d0fd3502 100644 --- a/Sources/SwiftDocC/Model/Rendering/RenderContentConvertible.swift +++ b/Sources/SwiftDocC/Model/Rendering/RenderContentConvertible.swift @@ -24,7 +24,7 @@ extension RenderableDirectiveConvertible { _ blockDirective: BlockDirective, with contentCompiler: inout RenderContentCompiler ) -> [any RenderContent] { - guard let directive = Self.init(from: blockDirective, for: contentCompiler.bundle) else { + guard let directive = Self.init(from: blockDirective, for: contentCompiler.inputs) else { return [] } diff --git a/Sources/SwiftDocC/Model/Rendering/RenderContext.swift b/Sources/SwiftDocC/Model/Rendering/RenderContext.swift index dade49b7a0..958160c8c0 100644 --- a/Sources/SwiftDocC/Model/Rendering/RenderContext.swift +++ b/Sources/SwiftDocC/Model/Rendering/RenderContext.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -17,21 +17,26 @@ import SymbolKit /// converting nodes in bulk, i.e. when converting a complete documentation model for example. public struct RenderContext { let documentationContext: DocumentationContext - let bundle: DocumentationBundle + let inputs: DocumentationContext.Inputs let renderer: DocumentationContentRenderer /// Creates a new render context. /// - Warning: Creating a render context pre-renders all content that the context provides. /// - Parameters: /// - documentationContext: A documentation context. - /// - bundle: A documentation bundle. - public init(documentationContext: DocumentationContext, bundle: DocumentationBundle) { + /// - inputs: The collection of inputs files that the context is created from. + public init(documentationContext: DocumentationContext, inputs: DocumentationContext.Inputs) { self.documentationContext = documentationContext - self.bundle = bundle - self.renderer = DocumentationContentRenderer(documentationContext: documentationContext, bundle: bundle) + self.inputs = inputs + self.renderer = DocumentationContentRenderer(documentationContext: documentationContext, inputs: inputs) createRenderedContent() } + @available(*, deprecated, renamed: "init(documentationContext:inputs:)", message: "Use 'init(documentationContext:inputs:)' instead. This deprecated API will be removed after 6.3 is released") + public init(documentationContext: DocumentationContext, bundle: DocumentationContext.Inputs) { + self.init(documentationContext: documentationContext, inputs: bundle) + } + /// The pre-rendered content per node reference. private(set) public var store = RenderReferenceStore() diff --git a/Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift b/Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift index 1fd747b15a..c95f98b483 100644 --- a/Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift +++ b/Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift @@ -134,7 +134,7 @@ public struct RenderNodeTranslator: SemanticVisitor { public mutating func visitTutorial(_ tutorial: Tutorial) -> (any RenderTree)? { var node = RenderNode(identifier: identifier, kind: .tutorial) - var hierarchyTranslator = RenderHierarchyTranslator(context: context, bundle: bundle) + var hierarchyTranslator = RenderHierarchyTranslator(context: context, inputs: inputs) if let hierarchy = hierarchyTranslator.visitTutorialTableOfContentsNode(identifier) { let tutorialTableOfContents = try! context.entity(with: hierarchy.tutorialTableOfContents).semantic as! TutorialTableOfContents @@ -315,7 +315,7 @@ public struct RenderNodeTranslator: SemanticVisitor { // Visits a container and expects the elements to be block level elements public mutating func visitMarkupContainer(_ markupContainer: MarkupContainer) -> (any RenderTree)? { - var contentCompiler = RenderContentCompiler(context: context, bundle: bundle, identifier: identifier) + var contentCompiler = RenderContentCompiler(context: context, inputs: inputs, identifier: identifier) let content = markupContainer.elements.reduce(into: [], { result, item in result.append(contentsOf: contentCompiler.visit(item))}) as! [RenderBlockContent] collectedTopicReferences.append(contentsOf: contentCompiler.collectedTopicReferences) // Copy all the image references found in the markup container. @@ -327,7 +327,7 @@ public struct RenderNodeTranslator: SemanticVisitor { // Visits a collection of inline markup elements. public mutating func visitMarkup(_ markup: [any Markup]) -> (any RenderTree)? { - var contentCompiler = RenderContentCompiler(context: context, bundle: bundle, identifier: identifier) + var contentCompiler = RenderContentCompiler(context: context, inputs: inputs, identifier: identifier) let content = markup.reduce(into: [], { result, item in result.append(contentsOf: contentCompiler.visit(item))}) as! [RenderInlineContent] collectedTopicReferences.append(contentsOf: contentCompiler.collectedTopicReferences) // Copy all the image references. @@ -401,7 +401,7 @@ public struct RenderNodeTranslator: SemanticVisitor { node.sections.append(visitResources(resources) as! ResourcesRenderSection) } - var hierarchyTranslator = RenderHierarchyTranslator(context: context, bundle: bundle) + var hierarchyTranslator = RenderHierarchyTranslator(context: context, inputs: inputs) if let (hierarchyVariants, _) = hierarchyTranslator.visitTutorialTableOfContentsNode(identifier, omittingChapters: true) { node.hierarchyVariants = hierarchyVariants collectedTopicReferences.append(contentsOf: hierarchyTranslator.collectedTopicReferences) @@ -419,7 +419,7 @@ public struct RenderNodeTranslator: SemanticVisitor { private mutating func createTopicRenderReferences() -> [String: any RenderReference] { var renderReferences: [String: any RenderReference] = [:] - let renderer = DocumentationContentRenderer(documentationContext: context, bundle: bundle) + let renderer = DocumentationContentRenderer(documentationContext: context, inputs: inputs) for reference in collectedTopicReferences { var renderReference: TopicRenderReference @@ -530,7 +530,7 @@ public struct RenderNodeTranslator: SemanticVisitor { } public mutating func visitTutorialReference(_ tutorialReference: TutorialReference) -> (any RenderTree)? { - switch context.resolve(tutorialReference.topic, in: bundle.rootReference) { + switch context.resolve(tutorialReference.topic, in: inputs.rootReference) { case let .failure(reference, _): return RenderReferenceIdentifier(reference.topicURL.absoluteString) case let .success(resolved): @@ -600,7 +600,7 @@ public struct RenderNodeTranslator: SemanticVisitor { public mutating func visitArticle(_ article: Article) -> (any RenderTree)? { var node = RenderNode(identifier: identifier, kind: .article) // Contains symbol references declared in the Topics section. - var topicSectionContentCompiler = RenderContentCompiler(context: context, bundle: bundle, identifier: identifier) + var topicSectionContentCompiler = RenderContentCompiler(context: context, inputs: inputs, identifier: identifier) node.metadata.title = article.title!.plainText @@ -624,7 +624,7 @@ public struct RenderNodeTranslator: SemanticVisitor { let documentationNode = try! context.entity(with: identifier) - var hierarchyTranslator = RenderHierarchyTranslator(context: context, bundle: bundle) + var hierarchyTranslator = RenderHierarchyTranslator(context: context, inputs: inputs) let hierarchyVariants = hierarchyTranslator.visitArticle(identifier) collectedTopicReferences.append(contentsOf: hierarchyTranslator.collectedTopicReferences) node.hierarchyVariants = hierarchyVariants @@ -806,7 +806,7 @@ public struct RenderNodeTranslator: SemanticVisitor { for: documentationNode, withTraits: allowedTraits, context: context, - bundle: bundle, + inputs: inputs, renderContext: renderContext, renderer: contentRenderer ) { @@ -878,7 +878,7 @@ public struct RenderNodeTranslator: SemanticVisitor { public mutating func visitTutorialArticle(_ article: TutorialArticle) -> (any RenderTree)? { var node = RenderNode(identifier: identifier, kind: .article) - var hierarchyTranslator = RenderHierarchyTranslator(context: context, bundle: bundle) + var hierarchyTranslator = RenderHierarchyTranslator(context: context, inputs: inputs) guard let hierarchy = hierarchyTranslator.visitTutorialTableOfContentsNode(identifier) else { // This tutorial article is not curated, so we don't generate a render node. // We've warned about this during semantic analysis. @@ -1029,7 +1029,7 @@ public struct RenderNodeTranslator: SemanticVisitor { ) -> [TaskGroupRenderSection] { return topics.taskGroups.compactMap { group in let supportedLanguages = group.directives[SupportedLanguage.directiveName]?.compactMap { - SupportedLanguage(from: $0, source: nil, for: bundle)?.language + SupportedLanguage(from: $0, source: nil, for: inputs)?.language } // If the task group has a set of supported languages, see if it should render for the allowed traits. @@ -1201,7 +1201,7 @@ public struct RenderNodeTranslator: SemanticVisitor { let identifier = identifier.addingSourceLanguages(documentationNode.availableSourceLanguages) var node = RenderNode(identifier: identifier, kind: .symbol) - var contentCompiler = RenderContentCompiler(context: context, bundle: bundle, identifier: identifier) + var contentCompiler = RenderContentCompiler(context: context, inputs: inputs, identifier: identifier) /* FIXME: We shouldn't be doing this kind of crawling here. @@ -1241,7 +1241,7 @@ public struct RenderNodeTranslator: SemanticVisitor { node.metadata.extendedModuleVariants = VariantCollection(from: symbol.extendedModuleVariants) - let defaultAvailability = defaultAvailability(for: bundle, moduleName: moduleName.symbolName, currentPlatforms: context.configuration.externalMetadata.currentPlatforms)? + let defaultAvailability = defaultAvailability(for: inputs, moduleName: moduleName.symbolName, currentPlatforms: context.configuration.externalMetadata.currentPlatforms)? .filter { $0.unconditionallyUnavailable != true } .sorted(by: AvailabilityRenderOrder.compare) @@ -1330,10 +1330,10 @@ public struct RenderNodeTranslator: SemanticVisitor { collectedTopicReferences.append(identifier) - let contentRenderer = DocumentationContentRenderer(documentationContext: context, bundle: bundle) + let contentRenderer = DocumentationContentRenderer(documentationContext: context, inputs: inputs) node.metadata.tags = contentRenderer.tags(for: identifier) - var hierarchyTranslator = RenderHierarchyTranslator(context: context, bundle: bundle) + var hierarchyTranslator = RenderHierarchyTranslator(context: context, inputs: inputs) let hierarchyVariants = hierarchyTranslator.visitSymbol(identifier) collectedTopicReferences.append(contentsOf: hierarchyTranslator.collectedTopicReferences) node.hierarchyVariants = hierarchyVariants @@ -1648,7 +1648,7 @@ public struct RenderNodeTranslator: SemanticVisitor { for: documentationNode, withTraits: allowedTraits, context: context, - bundle: bundle, + inputs: inputs, renderContext: renderContext, renderer: contentRenderer ), !seeAlso.references.isEmpty { @@ -1774,7 +1774,7 @@ public struct RenderNodeTranslator: SemanticVisitor { } var context: DocumentationContext - var bundle: DocumentationBundle + var inputs: DocumentationContext.Inputs var identifier: ResolvedTopicReference var imageReferences: [String: ImageReference] = [:] var videoReferences: [String: VideoReference] = [:] @@ -1808,7 +1808,7 @@ public struct RenderNodeTranslator: SemanticVisitor { } /// The default availability for modules in a given bundle and module. - mutating func defaultAvailability(for bundle: DocumentationBundle, moduleName: String, currentPlatforms: [String: PlatformVersion]?) -> [AvailabilityRenderItem]? { + mutating func defaultAvailability(for bundle: DocumentationContext.Inputs, moduleName: String, currentPlatforms: [String: PlatformVersion]?) -> [AvailabilityRenderItem]? { let identifier = BundleModuleIdentifier(bundle: bundle, moduleName: moduleName) // Cached availability @@ -1851,7 +1851,7 @@ public struct RenderNodeTranslator: SemanticVisitor { } private func variants(for documentationNode: DocumentationNode) -> [RenderNode.Variant] { - let generator = PresentationURLGenerator(context: context, baseURL: bundle.baseURL) + let generator = PresentationURLGenerator(context: context, baseURL: inputs.baseURL) var allVariants: [SourceLanguage: ResolvedTopicReference] = documentationNode.availableSourceLanguages.reduce(into: [:]) { partialResult, language in partialResult[language] = identifier @@ -2002,7 +2002,7 @@ public struct RenderNodeTranslator: SemanticVisitor { init( context: DocumentationContext, - bundle: DocumentationBundle, + inputs: DocumentationContext.Inputs, identifier: ResolvedTopicReference, renderContext: RenderContext? = nil, emitSymbolSourceFileURIs: Bool = false, @@ -2011,10 +2011,32 @@ public struct RenderNodeTranslator: SemanticVisitor { symbolIdentifiersWithExpandedDocumentation: [String]? = nil ) { self.context = context - self.bundle = bundle + self.inputs = inputs self.identifier = identifier self.renderContext = renderContext - self.contentRenderer = DocumentationContentRenderer(documentationContext: context, bundle: bundle) + self.contentRenderer = DocumentationContentRenderer(documentationContext: context, inputs: inputs) + self.shouldEmitSymbolSourceFileURIs = emitSymbolSourceFileURIs + self.shouldEmitSymbolAccessLevels = emitSymbolAccessLevels + self.sourceRepository = sourceRepository + self.symbolIdentifiersWithExpandedDocumentation = symbolIdentifiersWithExpandedDocumentation + } + + @available(*, deprecated, renamed: "init(context:inputs:identifier:renderContext:emitSymbolSourceFileURIs:emitSymbolAccessLevels:sourceRepository:symbolIdentifiersWithExpandedDocumentation:)") + init( + context: DocumentationContext, + bundle: DocumentationContext.Inputs, + identifier: ResolvedTopicReference, + renderContext: RenderContext? = nil, + emitSymbolSourceFileURIs: Bool = false, + emitSymbolAccessLevels: Bool = false, + sourceRepository: SourceRepository? = nil, + symbolIdentifiersWithExpandedDocumentation: [String]? = nil + ) { + self.context = context + self.inputs = bundle + self.identifier = identifier + self.renderContext = renderContext + self.contentRenderer = DocumentationContentRenderer(documentationContext: context, inputs: inputs) self.shouldEmitSymbolSourceFileURIs = emitSymbolSourceFileURIs self.shouldEmitSymbolAccessLevels = emitSymbolAccessLevels self.sourceRepository = sourceRepository @@ -2025,7 +2047,7 @@ public struct RenderNodeTranslator: SemanticVisitor { fileprivate typealias BundleModuleIdentifier = String extension BundleModuleIdentifier { - fileprivate init(bundle: DocumentationBundle, moduleName: String) { + fileprivate init(bundle: DocumentationContext.Inputs, moduleName: String) { self = "\(bundle.id):\(moduleName)" } } diff --git a/Sources/SwiftDocC/Model/Rendering/RenderReferenceStore.swift b/Sources/SwiftDocC/Model/Rendering/RenderReferenceStore.swift index d095303fc5..2b1a8eea25 100644 --- a/Sources/SwiftDocC/Model/Rendering/RenderReferenceStore.swift +++ b/Sources/SwiftDocC/Model/Rendering/RenderReferenceStore.swift @@ -38,7 +38,7 @@ public struct RenderReferenceStore: Codable { } /// Returns asset information for the given asset name. - public func content(forAssetNamed assetName: String, bundleID: DocumentationBundle.Identifier) -> DataAsset? { + public func content(forAssetNamed assetName: String, bundleID: DocumentationContext.Inputs.Identifier) -> DataAsset? { assets[AssetReference(assetName: assetName, bundleID: bundleID)] } } diff --git a/Sources/SwiftDocC/Semantics/Article/Article.swift b/Sources/SwiftDocC/Semantics/Article/Article.swift index aec17835f9..89877d6aa9 100644 --- a/Sources/SwiftDocC/Semantics/Article/Article.swift +++ b/Sources/SwiftDocC/Semantics/Article/Article.swift @@ -94,9 +94,9 @@ public final class Article: Semantic, MarkupConvertible, Abstracted, Redirected, /// - Parameters: /// - markup: The markup that makes up this article's content. /// - source: The location of the file that this article's content comes from. - /// - bundle: The documentation bundle that the source file belongs to. + /// - inputs: The documentation bundle that the source file belongs to. /// - problems: A mutable collection of problems to update with any problem encountered while initializing the article. - public convenience init?(from markup: any Markup, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from markup: any Markup, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { guard let title = markup.child(at: 0) as? Heading, title.level == 1 else { let range = markup.child(at: 0)?.range ?? SourceLocation(line: 1, column: 1, source: nil)..(severityIfFound: .warning, allowedArguments: [Semantics.Title.argumentName, Semantics.Layout.argumentName, Semantics.Eyebrow.argumentName]).analyze(directive, children: directive.children, source: source, problems: &problems) Semantic.Analyses.HasOnlyKnownDirectives(severityIfFound: .warning, allowedDirectives: [ImageMedia.directiveName, VideoMedia.directiveName]).analyze(directive, children: directive.children, source: source, problems: &problems) @@ -85,7 +85,7 @@ public final class ContentAndMedia: Semantic, DirectiveConvertible { let layout = Semantic.Analyses.DeprecatedArgument.unused(severityIfFound: .warning).analyze(directive, arguments: arguments, problems: &problems) - let (media, remainder) = Semantic.Analyses.HasExactlyOneMedia(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: bundle, problems: &problems) + let (media, remainder) = Semantic.Analyses.HasExactlyOneMedia(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: inputs, problems: &problems) let mediaPosition: MediaPosition if let firstChildDirective = directive.child(at: 0) as? BlockDirective, diff --git a/Sources/SwiftDocC/Semantics/DirectiveConvertable.swift b/Sources/SwiftDocC/Semantics/DirectiveConvertable.swift index fb2d4d6f9d..083a425cda 100644 --- a/Sources/SwiftDocC/Semantics/DirectiveConvertable.swift +++ b/Sources/SwiftDocC/Semantics/DirectiveConvertable.swift @@ -36,7 +36,7 @@ public protocol DirectiveConvertible { /// - source: The location of the source file that contains the markup for the parsed block directive. /// - bundle: The documentation bundle that the source file belongs to. /// - problems: An inout array of ``Problem`` to be collected for later diagnostic reporting. - init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) + init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationContext.Inputs, problems: inout [Problem]) /// Returns a Boolean value indicating whether the `DirectiveConvertible` recognizes the given directive. /// diff --git a/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/AutomaticDirectiveConvertible.swift b/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/AutomaticDirectiveConvertible.swift index bfd1ab53de..99922cc826 100644 --- a/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/AutomaticDirectiveConvertible.swift +++ b/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/AutomaticDirectiveConvertible.swift @@ -92,21 +92,20 @@ extension AutomaticDirectiveConvertible { /// the same function but supports collecting an array of problems for diagnostics. /// /// - Parameters: - /// - directive: The block directive that will be parsed - /// - source: An optional URL for the source location where this directive is written. - /// - bundle: The documentation bundle that owns the directive. - /// - context: The documentation context in which the bundle resides. + /// - directive: The block directive that will be parsed + /// - source: An optional URL for the source location where this directive is written. + /// - inputs: The collection of inputs files that the directive originates from. public init?( from directive: BlockDirective, source: URL? = nil, - for bundle: DocumentationBundle + for inputs: DocumentationContext.Inputs ) { var problems = [Problem]() self.init( from: directive, source: source, - for: bundle, + for: inputs, problems: &problems ) } @@ -114,7 +113,7 @@ extension AutomaticDirectiveConvertible { public init?( from directive: BlockDirective, source: URL?, - for bundle: DocumentationBundle, + for inputs: DocumentationContext.Inputs, problems: inout [Problem] ) { precondition(directive.name == Self.directiveName) @@ -144,7 +143,7 @@ extension AutomaticDirectiveConvertible { allowedValues: reflectedArgument.allowedValues, expectedFormat: reflectedArgument.expectedFormat, convert: { argumentValue in - return reflectedArgument.parseArgument(bundle, argumentValue) + return reflectedArgument.parseArgument(inputs, argumentValue) }, valueTypeDiagnosticName: reflectedArgument.typeDisplayName ) @@ -177,7 +176,7 @@ extension AutomaticDirectiveConvertible { childType: Comment.self, children: remainder, source: source, - for: bundle, + for: inputs, problems: &problems ) @@ -190,7 +189,7 @@ extension AutomaticDirectiveConvertible { parentDirective: directive, children: remainder, source: source, - for: bundle, + for: inputs, problems: &problems ) @@ -214,7 +213,7 @@ extension AutomaticDirectiveConvertible { parentDirective: directive, children: remainder, source: source, - for: bundle, + for: inputs, problems: &problems ) @@ -237,7 +236,7 @@ extension AutomaticDirectiveConvertible { childType: childDirective.type, children: remainder, source: source, - for: bundle, + for: inputs, problems: &problems ) @@ -251,7 +250,7 @@ extension AutomaticDirectiveConvertible { parentDirective: directive, children: remainder, source: source, - for: bundle, + for: inputs, problems: &problems ) diff --git a/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/DirectiveArgumentWrapper.swift b/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/DirectiveArgumentWrapper.swift index 83639012ac..e55a1087fe 100644 --- a/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/DirectiveArgumentWrapper.swift +++ b/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/DirectiveArgumentWrapper.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2022-2023 Apple Inc. and the Swift project authors + Copyright (c) 2022-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -19,7 +19,7 @@ protocol _DirectiveArgumentProtocol { var expectedFormat: String? { get } var hiddenFromDocumentation: Bool { get } - var parseArgument: (_ bundle: DocumentationBundle, _ argumentValue: String) -> (Any?) { get } + var parseArgument: (_ inputs: DocumentationContext.Inputs, _ argumentValue: String) -> (Any?) { get } func setProperty( on containingDirective: some AutomaticDirectiveConvertible, @@ -68,7 +68,7 @@ public struct DirectiveArgumentWrapped: _DirectiveArgumentProtocol { let expectedFormat: String? let hiddenFromDocumentation: Bool - let parseArgument: (_ bundle: DocumentationBundle, _ argumentValue: String) -> (Any?) + let parseArgument: (_ bundle: DocumentationContext.Inputs, _ argumentValue: String) -> (Any?) let defaultValue: Value? var storedAsOptional: Bool { @@ -99,7 +99,7 @@ public struct DirectiveArgumentWrapped: _DirectiveArgumentProtocol { init( wrappedValue: Value, name: _DirectiveArgumentName = .inferredFromPropertyName, - parseArgument: @escaping (_ bundle: DocumentationBundle, _ argumentValue: String) -> (Value?), + parseArgument: @escaping (_ bundle: DocumentationContext.Inputs, _ argumentValue: String) -> (Value?), allowedValues: [String]? = nil, expectedFormat: String? = nil, hiddenFromDocumentation: Bool = false @@ -118,7 +118,7 @@ public struct DirectiveArgumentWrapped: _DirectiveArgumentProtocol { @_disfavoredOverload init( name: _DirectiveArgumentName = .inferredFromPropertyName, - parseArgument: @escaping (_ bundle: DocumentationBundle, _ argumentValue: String) -> (Value?), + parseArgument: @escaping (_ bundle: DocumentationContext.Inputs, _ argumentValue: String) -> (Value?), allowedValues: [String]? = nil, expectedFormat: String? = nil, hiddenFromDocumentation: Bool = false @@ -137,7 +137,7 @@ public struct DirectiveArgumentWrapped: _DirectiveArgumentProtocol { private init( value: Value?, name: _DirectiveArgumentName, - transform: @escaping (_ bundle: DocumentationBundle, _ argumentValue: String) -> (Value?), + transform: @escaping (_ bundle: DocumentationContext.Inputs, _ argumentValue: String) -> (Value?), allowedValues: [String]?, expectedFormat: String?, required: Bool?, @@ -325,7 +325,7 @@ extension DirectiveArgumentWrapped where Value: _OptionalDirectiveArgument { @_disfavoredOverload init( name: _DirectiveArgumentName = .inferredFromPropertyName, - parseArgument: @escaping (_ bundle: DocumentationBundle, _ argumentValue: String) -> (Value?), + parseArgument: @escaping (_ bundle: DocumentationContext.Inputs, _ argumentValue: String) -> (Value?), allowedValues: [String]? = nil, hiddenFromDocumentation: Bool = false ) { @@ -336,7 +336,7 @@ extension DirectiveArgumentWrapped where Value: _OptionalDirectiveArgument { init( wrappedValue: Value, name: _DirectiveArgumentName = .inferredFromPropertyName, - parseArgument: @escaping (_ bundle: DocumentationBundle, _ argumentValue: String) -> (Value?), + parseArgument: @escaping (_ bundle: DocumentationContext.Inputs, _ argumentValue: String) -> (Value?), allowedValues: [String]? = nil, hiddenFromDocumentation: Bool = false ) { @@ -346,7 +346,7 @@ extension DirectiveArgumentWrapped where Value: _OptionalDirectiveArgument { private init( value: Value?, name: _DirectiveArgumentName, - parseArgument: @escaping (_ bundle: DocumentationBundle, _ argumentValue: String) -> (Value?), + parseArgument: @escaping (_ bundle: DocumentationContext.Inputs, _ argumentValue: String) -> (Value?), allowedValues: [String]? = nil, expectedFormat: String? = nil, hiddenFromDocumentation: Bool = false diff --git a/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/DirectiveMirror.swift b/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/DirectiveMirror.swift index fcc8856aa5..269ac213be 100644 --- a/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/DirectiveMirror.swift +++ b/Sources/SwiftDocC/Semantics/DirectiveInfrastructure/DirectiveMirror.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2022-2023 Apple Inc. and the Swift project authors + Copyright (c) 2022-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -172,7 +172,7 @@ extension DirectiveMirror { let propertyLabel: String let argument: any _DirectiveArgumentProtocol - let parseArgument: (_ bundle: DocumentationBundle, _ argumentValue: String) -> (Any?) + let parseArgument: (_ inputs: DocumentationContext.Inputs, _ argumentValue: String) -> (Any?) func setValue( on containingDirective: some AutomaticDirectiveConvertible, diff --git a/Sources/SwiftDocC/Semantics/DirectiveParser.swift b/Sources/SwiftDocC/Semantics/DirectiveParser.swift index 95d38624ca..dfe4bcee54 100644 --- a/Sources/SwiftDocC/Semantics/DirectiveParser.swift +++ b/Sources/SwiftDocC/Semantics/DirectiveParser.swift @@ -23,7 +23,7 @@ struct DirectiveParser { from markupElements: inout [any Markup], parentType: Semantic.Type, source: URL?, - bundle: DocumentationBundle, + inputs: DocumentationContext.Inputs, problems: inout [Problem] ) -> Directive? { let (directiveElements, remainder) = markupElements.categorize { markup -> Directive? in @@ -35,7 +35,7 @@ struct DirectiveParser { return Directive( from: childDirective, source: source, - for: bundle, + for: inputs, problems: &problems ) } diff --git a/Sources/SwiftDocC/Semantics/ExternalLinks/ExternalMarkupReferenceWalker.swift b/Sources/SwiftDocC/Semantics/ExternalLinks/ExternalMarkupReferenceWalker.swift index 69502f34f8..3ba0acede4 100644 --- a/Sources/SwiftDocC/Semantics/ExternalLinks/ExternalMarkupReferenceWalker.swift +++ b/Sources/SwiftDocC/Semantics/ExternalLinks/ExternalMarkupReferenceWalker.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -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: DocumentationBundle.Identifier + var localBundleID: DocumentationContext.Inputs.Identifier /// After walking a markup tree, all encountered external links are collected grouped by the bundle ID. - var collectedExternalLinks = [DocumentationBundle.Identifier: Set]() + var collectedExternalLinks = [DocumentationContext.Inputs.Identifier: Set]() /// Descends down the given elements' children. mutating func defaultVisit(_ markup: any Markup) { @@ -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.map({ DocumentationBundle.Identifier(rawValue: $0) }), + let bundleID = url.components.host.map({ DocumentationContext.Inputs.Identifier(rawValue: $0) }), bundleID != localBundleID else { return diff --git a/Sources/SwiftDocC/Semantics/ExternalLinks/ExternalReferenceWalker.swift b/Sources/SwiftDocC/Semantics/ExternalLinks/ExternalReferenceWalker.swift index b1f2021f4a..2cfa68e837 100644 --- a/Sources/SwiftDocC/Semantics/ExternalLinks/ExternalReferenceWalker.swift +++ b/Sources/SwiftDocC/Semantics/ExternalLinks/ExternalReferenceWalker.swift @@ -41,7 +41,7 @@ struct ExternalReferenceWalker: SemanticVisitor { private var markupResolver: ExternalMarkupReferenceWalker /// Collected unresolved external references, grouped by the bundle ID. - var collectedExternalReferences: [DocumentationBundle.Identifier: [UnresolvedTopicReference]] { + var collectedExternalReferences: [DocumentationContext.Inputs.Identifier: [UnresolvedTopicReference]] { return markupResolver.collectedExternalLinks.mapValues { links in links.map(UnresolvedTopicReference.init(topicURL:)) } @@ -49,7 +49,7 @@ struct ExternalReferenceWalker: SemanticVisitor { /// 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: DocumentationBundle.Identifier) { + init(localBundleID: DocumentationContext.Inputs.Identifier) { self.markupResolver = ExternalMarkupReferenceWalker(localBundleID: localBundleID) } diff --git a/Sources/SwiftDocC/Semantics/General Purpose Analyses/Extract.swift b/Sources/SwiftDocC/Semantics/General Purpose Analyses/Extract.swift index 38b3611ea0..0e521e4a20 100644 --- a/Sources/SwiftDocC/Semantics/General Purpose Analyses/Extract.swift +++ b/Sources/SwiftDocC/Semantics/General Purpose Analyses/Extract.swift @@ -18,12 +18,12 @@ extension Semantic.Analyses { public struct ExtractAll { public init() {} - public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) -> ([Child], remainder: MarkupContainer) { + public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) -> ([Child], remainder: MarkupContainer) { return Semantic.Analyses.extractAll( childType: Child.self, children: children, source: source, - for: bundle, + for: inputs, problems: &problems ) as! ([Child], MarkupContainer) } @@ -33,7 +33,7 @@ extension Semantic.Analyses { childType: any DirectiveConvertible.Type, children: some Sequence, source: URL?, - for bundle: DocumentationBundle, + for inputs: DocumentationContext.Inputs, problems: inout [Problem] ) -> ([any DirectiveConvertible], remainder: MarkupContainer) { let (candidates, remainder) = children.categorize { child -> BlockDirective? in @@ -44,7 +44,7 @@ extension Semantic.Analyses { return childDirective } let converted = candidates.compactMap { - childType.init(from: $0, source: source, for: bundle, problems: &problems) + childType.init(from: $0, source: source, for: inputs, problems: &problems) } return (converted, remainder: MarkupContainer(remainder)) } diff --git a/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasAtLeastOne.swift b/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasAtLeastOne.swift index 7c8172f0d1..d1bace0b01 100644 --- a/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasAtLeastOne.swift +++ b/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasAtLeastOne.swift @@ -25,7 +25,7 @@ extension Semantic.Analyses { _ directive: BlockDirective, children: some Sequence, source: URL?, - for bundle: DocumentationBundle, + for inputs: DocumentationContext.Inputs, problems: inout [Problem] ) -> ([Child], remainder: MarkupContainer) { Semantic.Analyses.extractAtLeastOne( @@ -33,7 +33,7 @@ extension Semantic.Analyses { parentDirective: directive, children: children, source: source, - for: bundle, + for: inputs, severityIfNotFound: severityIfNotFound, problems: &problems ) as! ([Child], MarkupContainer) @@ -45,7 +45,7 @@ extension Semantic.Analyses { parentDirective: BlockDirective, children: some Sequence, source: URL?, - for bundle: DocumentationBundle, + for bundle: DocumentationContext.Inputs, severityIfNotFound: DiagnosticSeverity? = .warning, problems: inout [Problem] ) -> ([any DirectiveConvertible], remainder: MarkupContainer) { diff --git a/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasAtMostOne.swift b/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasAtMostOne.swift index 93765fd5d3..bc9a4beb8d 100644 --- a/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasAtMostOne.swift +++ b/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasAtMostOne.swift @@ -16,13 +16,13 @@ extension Semantic.Analyses { Checks to see if a parent directive has at most one child directive of a specified type. If so, return that child and the remainder. */ public struct HasAtMostOne { - public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) -> (Child?, remainder: MarkupContainer) { + public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) -> (Child?, remainder: MarkupContainer) { return Semantic.Analyses.extractAtMostOne( childType: Child.self, parentDirective: directive, children: children, source: source, - for: bundle, + for: inputs, problems: &problems ) as! (Child?, MarkupContainer) } @@ -33,7 +33,7 @@ extension Semantic.Analyses { parentDirective: BlockDirective, children: some Sequence, source: URL?, - for bundle: DocumentationBundle, + for inputs: DocumentationContext.Inputs, severityIfNotFound: DiagnosticSeverity = .warning, problems: inout [Problem] ) -> ((any DirectiveConvertible)?, remainder: MarkupContainer) { @@ -67,7 +67,7 @@ extension Semantic.Analyses { problems.append(Problem(diagnostic: diagnostic, possibleSolutions: [])) } - return (childType.init(from: match, source: source, for: bundle, problems: &problems), MarkupContainer(remainder)) + return (childType.init(from: match, source: source, for: inputs, problems: &problems), MarkupContainer(remainder)) } } diff --git a/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasExactlyOne.swift b/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasExactlyOne.swift index aa05a6dd63..9f90e0172c 100644 --- a/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasExactlyOne.swift +++ b/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasExactlyOne.swift @@ -21,13 +21,13 @@ extension Semantic.Analyses { self.severityIfNotFound = severityIfNotFound } - public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) -> (Child?, remainder: MarkupContainer) { + public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) -> (Child?, remainder: MarkupContainer) { return Semantic.Analyses.extractExactlyOne( childType: Child.self, parentDirective: directive, children: children, source: source, - for: bundle, + for: inputs, severityIfNotFound: severityIfNotFound, problems: &problems ) as! (Child?, MarkupContainer) @@ -39,7 +39,7 @@ extension Semantic.Analyses { parentDirective: BlockDirective, children: some Sequence, source: URL?, - for bundle: DocumentationBundle, + for inputs: DocumentationContext.Inputs, severityIfNotFound: DiagnosticSeverity? = .warning, problems: inout [Problem] ) -> ((any DirectiveConvertible)?, remainder: MarkupContainer) { @@ -89,7 +89,7 @@ extension Semantic.Analyses { } } - return (childType.init(from: candidate, source: source, for: bundle, problems: &problems), MarkupContainer(remainder)) + return (childType.init(from: candidate, source: source, for: inputs, problems: &problems), MarkupContainer(remainder)) } /// Checks a parent directive for the presence of exactly one of two child directives---but not both---to be converted to a type ``SemanticAnalysis/Result``. If so, return that child and the remainder. @@ -99,7 +99,7 @@ extension Semantic.Analyses { self.severityIfNotFound = severityIfNotFound } - public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) -> (Child1?, Child2?, remainder: MarkupContainer) { + public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for bundle: DocumentationContext.Inputs, problems: inout [Problem]) -> (Child1?, Child2?, remainder: MarkupContainer) { let (candidates, remainder) = children.categorize { child -> BlockDirective? in guard let childDirective = child as? BlockDirective else { return nil @@ -149,7 +149,7 @@ extension Semantic.Analyses { self.severityIfNotFound = severityIfNotFound } - public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) -> ((any Media)?, remainder: MarkupContainer) { + public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for bundle: DocumentationContext.Inputs, problems: inout [Problem]) -> ((any Media)?, remainder: MarkupContainer) { let (foundImage, foundVideo, remainder) = HasExactlyOneOf(severityIfNotFound: severityIfNotFound).analyze(directive, children: children, source: source, for: bundle, problems: &problems) return (foundImage ?? foundVideo, remainder) } @@ -162,7 +162,7 @@ extension Semantic.Analyses { self.severityIfNotFound = severityIfNotFound } - public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) -> ((any Media)?, remainder: MarkupContainer) { + public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for bundle: DocumentationContext.Inputs, problems: inout [Problem]) -> ((any Media)?, remainder: MarkupContainer) { let (mediaDirectives, remainder) = children.categorize { child -> BlockDirective? in guard let childDirective = child as? BlockDirective else { return nil diff --git a/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasOnlySequentialHeadings.swift b/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasOnlySequentialHeadings.swift index b7515b4efa..d48c41e609 100644 --- a/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasOnlySequentialHeadings.swift +++ b/Sources/SwiftDocC/Semantics/General Purpose Analyses/HasOnlySequentialHeadings.swift @@ -36,7 +36,7 @@ extension Semantic.Analyses { } /// Returns all valid headings. - @discardableResult public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for _: DocumentationBundle, problems: inout [Problem]) -> [Heading] { + @discardableResult public func analyze(_ directive: BlockDirective, children: some Sequence, source: URL?, for _: DocumentationContext.Inputs, problems: inout [Problem]) -> [Heading] { var currentHeadingLevel = startingFromLevel var headings: [Heading] = [] for case let child as Heading in children { diff --git a/Sources/SwiftDocC/Semantics/MarkupReferenceResolver.swift b/Sources/SwiftDocC/Semantics/MarkupReferenceResolver.swift index 8f34a30d46..c103506f25 100644 --- a/Sources/SwiftDocC/Semantics/MarkupReferenceResolver.swift +++ b/Sources/SwiftDocC/Semantics/MarkupReferenceResolver.swift @@ -44,13 +44,13 @@ private func removedLinkDestinationProblem(reference: ResolvedTopicReference, ra */ struct MarkupReferenceResolver: MarkupRewriter { var context: DocumentationContext - var bundle: DocumentationBundle + var inputs: DocumentationContext.Inputs var problems = [Problem]() var rootReference: ResolvedTopicReference - init(context: DocumentationContext, bundle: DocumentationBundle, rootReference: ResolvedTopicReference) { + init(context: DocumentationContext, inputs: DocumentationContext.Inputs, rootReference: ResolvedTopicReference) { self.context = context - self.bundle = bundle + self.inputs = inputs self.rootReference = rootReference } @@ -84,14 +84,14 @@ struct MarkupReferenceResolver: MarkupRewriter { return nil } - let uncuratedArticleMatch = context.uncuratedArticles[bundle.articlesDocumentationRootReference.appendingPathOfReference(unresolved)]?.source + let uncuratedArticleMatch = context.uncuratedArticles[inputs.articlesDocumentationRootReference.appendingPathOfReference(unresolved)]?.source problems.append(unresolvedReferenceProblem(source: range?.source, range: range, severity: severity, uncuratedArticleMatch: uncuratedArticleMatch, errorInfo: error, fromSymbolLink: fromSymbolLink)) return nil } } mutating func visitImage(_ image: Image) -> (any Markup)? { - if let reference = image.reference(in: bundle), !context.resourceExists(with: reference) { + if let reference = image.reference(in: inputs), !context.resourceExists(with: reference) { problems.append(unresolvedResourceProblem(resource: reference, source: image.range?.source, range: image.range, severity: .warning)) } @@ -172,7 +172,7 @@ struct MarkupReferenceResolver: MarkupRewriter { switch blockDirective.name { case Snippet.directiveName: var problems = [Problem]() - guard let snippet = Snippet(from: blockDirective, source: source, for: bundle, problems: &problems) else { + guard let snippet = Snippet(from: blockDirective, source: source, for: inputs, problems: &problems) else { return blockDirective } @@ -192,7 +192,7 @@ struct MarkupReferenceResolver: MarkupRewriter { return blockDirective } case ImageMedia.directiveName: - guard let imageMedia = ImageMedia(from: blockDirective, source: source, for: bundle) else { + guard let imageMedia = ImageMedia(from: blockDirective, source: source, for: inputs) else { return blockDirective } @@ -210,7 +210,7 @@ struct MarkupReferenceResolver: MarkupRewriter { return blockDirective case VideoMedia.directiveName: - guard let videoMedia = VideoMedia(from: blockDirective, source: source, for: bundle) else { + guard let videoMedia = VideoMedia(from: blockDirective, source: source, for: inputs) else { return blockDirective } diff --git a/Sources/SwiftDocC/Semantics/Metadata/CallToAction.swift b/Sources/SwiftDocC/Semantics/Metadata/CallToAction.swift index 569bf8c81e..b73b25e057 100644 --- a/Sources/SwiftDocC/Semantics/Metadata/CallToAction.swift +++ b/Sources/SwiftDocC/Semantics/Metadata/CallToAction.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2022-2023 Apple Inc. and the Swift project authors + Copyright (c) 2022-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -150,12 +150,12 @@ public final class CallToAction: Semantic, AutomaticDirectiveConvertible { extension CallToAction { func resolveFile( - for bundle: DocumentationBundle, + for inputs: DocumentationContext.Inputs, in context: DocumentationContext, problems: inout [Problem]) -> ResourceReference? { if let file = self.file { - if context.resolveAsset(named: file.url.lastPathComponent, in: bundle.rootReference) == nil { + if context.resolveAsset(named: file.url.lastPathComponent, in: inputs.rootReference) == nil { problems.append(.init( diagnostic: Diagnostic( source: url, diff --git a/Sources/SwiftDocC/Semantics/ReferenceResolver.swift b/Sources/SwiftDocC/Semantics/ReferenceResolver.swift index 2bb44a90ec..c896f8c05c 100644 --- a/Sources/SwiftDocC/Semantics/ReferenceResolver.swift +++ b/Sources/SwiftDocC/Semantics/ReferenceResolver.swift @@ -96,7 +96,7 @@ struct ReferenceResolver: SemanticVisitor { var context: DocumentationContext /// The bundle in which visited documents reside. - var bundle: DocumentationBundle + var inputs: DocumentationContext.Inputs /// Problems found while trying to resolve references. var problems = [Problem]() @@ -106,10 +106,10 @@ struct ReferenceResolver: SemanticVisitor { /// If the documentation is inherited, the reference of the parent symbol. var inheritanceParentReference: ResolvedTopicReference? - init(context: DocumentationContext, bundle: DocumentationBundle, rootReference: ResolvedTopicReference? = nil, inheritanceParentReference: ResolvedTopicReference? = nil) { + init(context: DocumentationContext, inputs: DocumentationContext.Inputs, rootReference: ResolvedTopicReference? = nil, inheritanceParentReference: ResolvedTopicReference? = nil) { self.context = context - self.bundle = bundle - self.rootReference = rootReference ?? bundle.rootReference + self.inputs = inputs + self.rootReference = rootReference ?? inputs.rootReference self.inheritanceParentReference = inheritanceParentReference } @@ -119,7 +119,7 @@ struct ReferenceResolver: SemanticVisitor { return .success(resolved) case let .failure(unresolved, error): - let uncuratedArticleMatch = context.uncuratedArticles[bundle.documentationRootReference.appendingPathOfReference(unresolved)]?.source + let uncuratedArticleMatch = context.uncuratedArticles[inputs.documentationRootReference.appendingPathOfReference(unresolved)]?.source problems.append(unresolvedReferenceProblem(source: range?.source, range: range, severity: severity, uncuratedArticleMatch: uncuratedArticleMatch, errorInfo: error, fromSymbolLink: false)) return .failure(unresolved, error) } @@ -172,9 +172,9 @@ struct ReferenceResolver: SemanticVisitor { // Change the context of the project file to `download` if let projectFiles = tutorial.projectFiles, - var resolvedDownload = context.resolveAsset(named: projectFiles.path, in: bundle.rootReference) { + var resolvedDownload = context.resolveAsset(named: projectFiles.path, in: inputs.rootReference) { resolvedDownload.context = .download - context.updateAsset(named: projectFiles.path, asset: resolvedDownload, in: bundle.rootReference) + context.updateAsset(named: projectFiles.path, asset: resolvedDownload, in: inputs.rootReference) } return Tutorial(originalMarkup: tutorial.originalMarkup, durationMinutes: tutorial.durationMinutes, projectFiles: tutorial.projectFiles, requirements: newRequirements, intro: newIntro, sections: newSections, assessments: newAssessments, callToActionImage: newCallToActionImage, redirects: tutorial.redirects) @@ -215,7 +215,7 @@ struct ReferenceResolver: SemanticVisitor { } mutating func visitMarkupContainer(_ markupContainer: MarkupContainer) -> Semantic { - var markupResolver = MarkupReferenceResolver(context: context, bundle: bundle, rootReference: rootReference) + var markupResolver = MarkupReferenceResolver(context: context, inputs: inputs, rootReference: rootReference) let parent = inheritanceParentReference let context = self.context @@ -315,7 +315,7 @@ struct ReferenceResolver: SemanticVisitor { // i.e. doc:/${SOME_TECHNOLOGY}/${PROJECT} or doc://${BUNDLE_ID}/${SOME_TECHNOLOGY}/${PROJECT} switch tutorialReference.topic { case .unresolved: - let maybeResolved = resolve(tutorialReference.topic, in: bundle.tutorialsContainerReference, + let maybeResolved = resolve(tutorialReference.topic, in: inputs.tutorialsContainerReference, range: tutorialReference.originalMarkup.range, severity: .warning) return TutorialReference(originalMarkup: tutorialReference.originalMarkup, tutorial: .resolved(maybeResolved)) @@ -369,10 +369,10 @@ struct ReferenceResolver: SemanticVisitor { visitMarkupContainer($0) as? MarkupContainer } // If there's a call to action with a local-file reference, change its context to `download` - if let downloadFile = article.metadata?.callToAction?.resolveFile(for: bundle, in: context, problems: &problems), - var resolvedDownload = context.resolveAsset(named: downloadFile.path, in: bundle.rootReference) { + if let downloadFile = article.metadata?.callToAction?.resolveFile(for: inputs, in: context, problems: &problems), + var resolvedDownload = context.resolveAsset(named: downloadFile.path, in: inputs.rootReference) { resolvedDownload.context = .download - context.updateAsset(named: downloadFile.path, asset: resolvedDownload, in: bundle.rootReference) + context.updateAsset(named: downloadFile.path, asset: resolvedDownload, in: inputs.rootReference) } return Article( @@ -543,15 +543,15 @@ fileprivate extension URL { } extension Image { - func reference(in bundle: DocumentationBundle) -> ResourceReference? { + func reference(in inputs: DocumentationContext.Inputs) -> ResourceReference? { guard let source else { - return ResourceReference(bundleID: bundle.id, path: "") + return ResourceReference(bundleID: inputs.id, path: "") } if let url = URL(string: source), url.isLikelyWebURL { return nil } else { - return ResourceReference(bundleID: bundle.id, path: source) + return ResourceReference(bundleID: inputs.id, path: source) } } } diff --git a/Sources/SwiftDocC/Semantics/SemanticAnalyzer.swift b/Sources/SwiftDocC/Semantics/SemanticAnalyzer.swift index 7af7e5999a..27cb006478 100644 --- a/Sources/SwiftDocC/Semantics/SemanticAnalyzer.swift +++ b/Sources/SwiftDocC/Semantics/SemanticAnalyzer.swift @@ -14,11 +14,11 @@ import Markdown struct SemanticAnalyzer: MarkupVisitor { var problems = [Problem]() let source: URL? - let bundle: DocumentationBundle + let inputs: DocumentationContext.Inputs - init(source: URL?, bundle: DocumentationBundle) { + init(source: URL?, inputs: DocumentationContext.Inputs) { self.source = source - self.bundle = bundle + self.inputs = inputs } private mutating func analyzeChildren(of markup: any Markup) -> [Semantic] { @@ -51,13 +51,13 @@ struct SemanticAnalyzer: MarkupVisitor { .list(finalConjunction: .or) if let source { - if !topLevelChildren.isEmpty, !DocumentationBundleFileTypes.isTutorialFile(source) { + if !topLevelChildren.isEmpty, !DocumentationInputFileTypes.isTutorialFile(source) { // Only tutorials support top level directives. This document has top level directives but is not a tutorial file. let directiveName = type(of: topLevelChildren.first! as! (any DirectiveConvertible)).directiveName let diagnostic = Diagnostic(source: source, severity: .warning, range: document.range, identifier: "org.swift.docc.unsupportedTopLevelChild", summary: "Found unsupported \(directiveName.singleQuoted) directive in '.\(source.pathExtension)' file", explanation: "Only '.tutorial' files support top-level directives") problems.append(Problem(diagnostic: diagnostic, possibleSolutions: [])) return nil - } else if topLevelChildren.isEmpty, !DocumentationBundleFileTypes.isReferenceDocumentationFile(source) { + } else if topLevelChildren.isEmpty, !DocumentationInputFileTypes.isReferenceDocumentationFile(source) { // Only reference documentation support all markdown content. This document has no top level directives but is not a reference documentation file. let diagnostic = Diagnostic( source: source, @@ -77,7 +77,7 @@ struct SemanticAnalyzer: MarkupVisitor { } if topLevelChildren.isEmpty { - guard let article = Article(from: document, source: source, for: bundle, problems: &problems) else { + guard let article = Article(from: document, source: source, for: inputs, problems: &problems) else { // We've already diagnosed the invalid article. return nil } @@ -100,58 +100,58 @@ struct SemanticAnalyzer: MarkupVisitor { mutating func visitBlockDirective(_ blockDirective: BlockDirective) -> Semantic? { switch blockDirective.name { case TutorialTableOfContents.directiveName: - return TutorialTableOfContents(from: blockDirective, source: source, for: bundle, problems: &problems) + return TutorialTableOfContents(from: blockDirective, source: source, for: inputs, problems: &problems) case Volume.directiveName: - return Volume(from: blockDirective, source: source, for: bundle, problems: &problems) + return Volume(from: blockDirective, source: source, for: inputs, problems: &problems) case Chapter.directiveName: - return Chapter(from: blockDirective, source: source, for: bundle, problems: &problems) + return Chapter(from: blockDirective, source: source, for: inputs, problems: &problems) case TutorialReference.directiveName: - return TutorialReference(from: blockDirective, source: source, for: bundle, problems: &problems) + return TutorialReference(from: blockDirective, source: source, for: inputs, problems: &problems) case ContentAndMedia.directiveName: - return ContentAndMedia(from: blockDirective, source: source, for: bundle, problems: &problems) + return ContentAndMedia(from: blockDirective, source: source, for: inputs, problems: &problems) case Intro.directiveName: - return Intro(from: blockDirective, source: source, for: bundle, problems: &problems) + return Intro(from: blockDirective, source: source, for: inputs, problems: &problems) case ImageMedia.directiveName: - return ImageMedia(from: blockDirective, source: source, for: bundle, problems: &problems) + return ImageMedia(from: blockDirective, source: source, for: inputs, problems: &problems) case VideoMedia.directiveName: - return VideoMedia(from: blockDirective, source: source, for: bundle, problems: &problems) + return VideoMedia(from: blockDirective, source: source, for: inputs, problems: &problems) case Tutorial.directiveName: - return Tutorial(from: blockDirective, source: source, for: bundle, problems: &problems) + return Tutorial(from: blockDirective, source: source, for: inputs, problems: &problems) case TutorialArticle.directiveName: - return TutorialArticle(from: blockDirective, source: source, for: bundle, problems: &problems) + return TutorialArticle(from: blockDirective, source: source, for: inputs, problems: &problems) case XcodeRequirement.directiveName: - return XcodeRequirement(from: blockDirective, source: source, for: bundle, problems: &problems) + return XcodeRequirement(from: blockDirective, source: source, for: inputs, problems: &problems) case Assessments.directiveName: - return Assessments(from: blockDirective, source: source, for: bundle, problems: &problems) + return Assessments(from: blockDirective, source: source, for: inputs, problems: &problems) case MultipleChoice.directiveName: - return MultipleChoice(from: blockDirective, source: source, for: bundle, problems: &problems) + return MultipleChoice(from: blockDirective, source: source, for: inputs, problems: &problems) case Choice.directiveName: - return Choice(from: blockDirective, source: source, for: bundle, problems: &problems) + return Choice(from: blockDirective, source: source, for: inputs, problems: &problems) case Justification.directiveName: - return Justification(from: blockDirective, source: source, for: bundle, problems: &problems) + return Justification(from: blockDirective, source: source, for: inputs, problems: &problems) case TutorialSection.directiveName: - return TutorialSection(from: blockDirective, source: source, for: bundle, problems: &problems) + return TutorialSection(from: blockDirective, source: source, for: inputs, problems: &problems) case Step.directiveName: - return Step(from: blockDirective, source: source, for: bundle, problems: &problems) + return Step(from: blockDirective, source: source, for: inputs, problems: &problems) case Resources.directiveName: - return Resources(from: blockDirective, source: source, for: bundle, problems: &problems) + return Resources(from: blockDirective, source: source, for: inputs, problems: &problems) case Comment.directiveName: - return Comment(from: blockDirective, source: source, for: bundle, problems: &problems) + return Comment(from: blockDirective, source: source, for: inputs, problems: &problems) case DeprecationSummary.directiveName: - return DeprecationSummary(from: blockDirective, source: source, for: bundle, problems: &problems) + return DeprecationSummary(from: blockDirective, source: source, for: inputs, problems: &problems) case Metadata.directiveName: - return Metadata(from: blockDirective, source: source, for: bundle, problems: &problems) + return Metadata(from: blockDirective, source: source, for: inputs, problems: &problems) case Redirect.directiveName: - return Redirect(from: blockDirective, source: source, for: bundle, problems: &problems) + return Redirect(from: blockDirective, source: source, for: inputs, problems: &problems) case DocumentationExtension.directiveName: - return DocumentationExtension(from: blockDirective, source: source, for: bundle, problems: &problems) + return DocumentationExtension(from: blockDirective, source: source, for: inputs, problems: &problems) case Snippet.directiveName: // A snippet directive does not need to stay around as a Semantic object. // we only need to check the path argument and that it doesn't // have any inner content as a convenience to the author. // The path will resolve as a symbol link later in the // MarkupReferenceResolver. - _ = Snippet(from: blockDirective, source: source, for: bundle, problems: &problems) + _ = Snippet(from: blockDirective, source: source, for: inputs, problems: &problems) return nil case Options.directiveName: return nil @@ -166,7 +166,7 @@ struct SemanticAnalyzer: MarkupVisitor { guard let directive = directiveType.init( from: blockDirective, source: source, - for: bundle, + for: inputs, problems: &problems ) else { return nil diff --git a/Sources/SwiftDocC/Semantics/Snippets/Snippet.swift b/Sources/SwiftDocC/Semantics/Snippets/Snippet.swift index 417f4c5dc3..446d6d66ff 100644 --- a/Sources/SwiftDocC/Semantics/Snippets/Snippet.swift +++ b/Sources/SwiftDocC/Semantics/Snippets/Snippet.swift @@ -65,7 +65,7 @@ public final class Snippet: Semantic, AutomaticDirectiveConvertible { extension Snippet: RenderableDirectiveConvertible { func render(with contentCompiler: inout RenderContentCompiler) -> [any RenderContent] { - guard let snippet = Snippet(from: originalMarkup, for: contentCompiler.bundle) else { + guard let snippet = Snippet(from: originalMarkup, for: contentCompiler.inputs) else { return [] } diff --git a/Sources/SwiftDocC/Semantics/Technology/Resources/Resources.swift b/Sources/SwiftDocC/Semantics/Technology/Resources/Resources.swift index ba00a1b633..cefa682ce3 100644 --- a/Sources/SwiftDocC/Semantics/Technology/Resources/Resources.swift +++ b/Sources/SwiftDocC/Semantics/Technology/Resources/Resources.swift @@ -54,7 +54,7 @@ public final class Resources: Semantic, DirectiveConvertible, Abstracted, Redire self.redirects = redirects } - public convenience init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { precondition(directive.name == Resources.directiveName) var remainder: [any Markup] @@ -76,7 +76,7 @@ public final class Resources: Semantic, DirectiveConvertible, Abstracted, Redire guard let childDirective = child as? BlockDirective, childDirective.name == Redirect.directiveName else { return nil } - return Redirect(from: childDirective, source: source, for: bundle, problems: &problems) + return Redirect(from: childDirective, source: source, for: inputs, problems: &problems) } let tiles: [Tile] @@ -84,7 +84,7 @@ public final class Resources: Semantic, DirectiveConvertible, Abstracted, Redire guard let childDirective = child as? BlockDirective, Tile.DirectiveNames(rawValue: childDirective.name) != nil else { return nil } - return Tile(from: childDirective, source: source, for: bundle, problems: &problems) + return Tile(from: childDirective, source: source, for: inputs, problems: &problems) } var seenTileDirectiveNames = Set() diff --git a/Sources/SwiftDocC/Semantics/Technology/Resources/Tile.swift b/Sources/SwiftDocC/Semantics/Technology/Resources/Tile.swift index a8975c57d6..2e1463d153 100644 --- a/Sources/SwiftDocC/Semantics/Technology/Resources/Tile.swift +++ b/Sources/SwiftDocC/Semantics/Technology/Resources/Tile.swift @@ -166,7 +166,7 @@ public final class Tile: Semantic, DirectiveConvertible { self.init(originalMarkup: directive, identifier: tileIdentifier, title: title, destination: destination, content: MarkupContainer(directive.children)) } - public convenience init?(from directive: BlockDirective, source: URL?, for _: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for _: DocumentationContext.Inputs, problems: inout [Problem]) { switch directive.name { case Tile.DirectiveNames.documentation.rawValue: self.init(genericTile: directive, diff --git a/Sources/SwiftDocC/Semantics/Technology/TutorialTableOfContents.swift b/Sources/SwiftDocC/Semantics/Technology/TutorialTableOfContents.swift index 7e7098c0fb..00f6822112 100644 --- a/Sources/SwiftDocC/Semantics/Technology/TutorialTableOfContents.swift +++ b/Sources/SwiftDocC/Semantics/Technology/TutorialTableOfContents.swift @@ -59,7 +59,7 @@ public final class TutorialTableOfContents: Semantic, DirectiveConvertible, Abst } } - public convenience init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { precondition(directive.name == TutorialTableOfContents.directiveName) let arguments = Semantic.Analyses.HasOnlyKnownArguments(severityIfFound: .warning, allowedArguments: [Semantics.Name.argumentName]).analyze(directive, children: directive.children, source: source, problems: &problems) @@ -67,15 +67,15 @@ public final class TutorialTableOfContents: Semantic, DirectiveConvertible, Abst Semantic.Analyses.HasOnlyKnownDirectives(severityIfFound: .warning, allowedDirectives: [Intro.directiveName, Volume.directiveName, Chapter.directiveName, Resources.directiveName, Redirect.directiveName]).analyze(directive, children: directive.children, source: source, problems: &problems) let requiredName = Semantic.Analyses.HasArgument(severityIfNotFound: .warning).analyze(directive, arguments: arguments, problems: &problems) - let requiredIntro = Semantic.Analyses.HasExactlyOne(severityIfNotFound: .warning).analyze(directive, children: directive.children, source: source, for: bundle, problems: &problems).0 + let requiredIntro = Semantic.Analyses.HasExactlyOne(severityIfNotFound: .warning).analyze(directive, children: directive.children, source: source, for: inputs, problems: &problems).0 var volumes: [Volume] var remainder: MarkupContainer - (volumes, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: bundle, problems: &problems) + (volumes, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: inputs, problems: &problems) // Retrieve chapters outside volumes. let chapters: [Chapter] - (chapters, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: bundle, problems: &problems) + (chapters, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: inputs, problems: &problems) if !chapters.isEmpty { if !volumes.isEmpty { @@ -94,10 +94,10 @@ public final class TutorialTableOfContents: Semantic, DirectiveConvertible, Abst } let resources: Resources? - (resources, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (resources, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) let redirects: [Redirect] - (redirects, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (redirects, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) guard let name = requiredName, let intro = requiredIntro else { diff --git a/Sources/SwiftDocC/Semantics/Technology/Volume/Volume.swift b/Sources/SwiftDocC/Semantics/Technology/Volume/Volume.swift index 40e606ca6a..900357def3 100644 --- a/Sources/SwiftDocC/Semantics/Technology/Volume/Volume.swift +++ b/Sources/SwiftDocC/Semantics/Technology/Volume/Volume.swift @@ -63,7 +63,7 @@ public final class Volume: Semantic, DirectiveConvertible, Abstracted, Redirecte } } - public convenience init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { precondition(directive.name == Volume.directiveName) let arguments = Semantic.Analyses.HasOnlyKnownArguments(severityIfFound: .warning, allowedArguments: [Semantics.Name.argumentName]).analyze(directive, children: directive.children, source: source, problems: &problems) @@ -74,14 +74,14 @@ public final class Volume: Semantic, DirectiveConvertible, Abstracted, Redirecte let image: ImageMedia? var remainder: MarkupContainer - (image, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: .warning).analyze(directive, children: directive.children, source: source, for: bundle, problems: &problems) + (image, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: .warning).analyze(directive, children: directive.children, source: source, for: inputs, problems: &problems) let chapters: [Chapter] - (chapters, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: .warning).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (chapters, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: .warning).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) _ = Semantic.Analyses.HasContent(additionalContext: "A \(Volume.directiveName.singleQuoted) directive should at least have a sentence summarizing what the reader will learn").analyze(directive, children: remainder, source: source, problems: &problems) let redirects: [Redirect] - (redirects, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (redirects, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) guard let name = requiredName else { return nil diff --git a/Sources/SwiftDocC/Semantics/Tutorial/Assessments/Multiple Choice/MultipleChoice.swift b/Sources/SwiftDocC/Semantics/Tutorial/Assessments/Multiple Choice/MultipleChoice.swift index 3b8eecfa2f..8550187bc6 100644 --- a/Sources/SwiftDocC/Semantics/Tutorial/Assessments/Multiple Choice/MultipleChoice.swift +++ b/Sources/SwiftDocC/Semantics/Tutorial/Assessments/Multiple Choice/MultipleChoice.swift @@ -51,7 +51,7 @@ public final class MultipleChoice: Semantic, DirectiveConvertible { self.choices = choices } - public convenience init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { precondition(directive.name == MultipleChoice.directiveName) _ = Semantic.Analyses.HasOnlyKnownArguments(severityIfFound: .warning, allowedArguments: []).analyze(directive, children: directive.children, source: source, problems: &problems) @@ -70,7 +70,7 @@ public final class MultipleChoice: Semantic, DirectiveConvertible { } let choices: [Choice] - (choices, remainder) = Semantic.Analyses.ExtractAll().analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (choices, remainder) = Semantic.Analyses.ExtractAll().analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) if choices.count < 2 || choices.count > 4 { let diagnostic = Diagnostic(source: source, severity: .warning, range: directive.range, identifier: "org.swift.docc.\(MultipleChoice.self).CorrectNumberOfChoices", summary: "`\(MultipleChoice.directiveName)` should contain 2-4 `\(Choice.directiveName)` child directives") @@ -115,7 +115,7 @@ public final class MultipleChoice: Semantic, DirectiveConvertible { } let images: [ImageMedia] - (images, remainder) = Semantic.Analyses.ExtractAll().analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (images, remainder) = Semantic.Analyses.ExtractAll().analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) if images.count > 1 { for extraneousImage in images.suffix(from: 1) { diff --git a/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Code.swift b/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Code.swift index ceca8cb7f0..f91c530b3a 100644 --- a/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Code.swift +++ b/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Code.swift @@ -59,7 +59,7 @@ public final class Code: Semantic, DirectiveConvertible { self.preview = preview } - public convenience init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { precondition(directive.name == Code.directiveName) let arguments = Semantic.Analyses.HasOnlyKnownArguments(severityIfFound: .warning, allowedArguments: [Semantics.File.argumentName, Semantics.PreviousFile.argumentName, Semantics.Name.argumentName, Semantics.ResetDiff.argumentName]).analyze(directive, children: directive.children, source: source, problems: &problems) @@ -67,7 +67,7 @@ public final class Code: Semantic, DirectiveConvertible { Semantic.Analyses.HasOnlyKnownDirectives(severityIfFound: .warning, allowedDirectives: [ImageMedia.directiveName, VideoMedia.directiveName]).analyze(directive, children: directive.children, source: source, problems: &problems) guard let requiredFileReference = Semantic.Analyses.HasArgument(severityIfNotFound: .warning).analyze(directive, arguments: arguments, problems: &problems) else { return nil } - let fileReference = ResourceReference(bundleID: bundle.id, path: requiredFileReference) + let fileReference = ResourceReference(bundleID: inputs.id, path: requiredFileReference) guard let requiredFileName = Semantic.Analyses.HasArgument(severityIfNotFound: .warning).analyze(directive, arguments: arguments, problems: &problems) else { return nil } @@ -80,10 +80,10 @@ public final class Code: Semantic, DirectiveConvertible { shouldResetDiff = false } - let (optionalPreview, _) = Semantic.Analyses.HasExactlyOneImageOrVideoMedia(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: bundle, problems: &problems) + let (optionalPreview, _) = Semantic.Analyses.HasExactlyOneImageOrVideoMedia(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: inputs, problems: &problems) let optionalPreviousFileReference = Semantic.Analyses.HasArgument(severityIfNotFound: nil).analyze(directive, arguments: arguments, problems: &problems).map { argument in - ResourceReference(bundleID: bundle.id, path: argument) + ResourceReference(bundleID: inputs.id, path: argument) } self.init(originalMarkup: directive, fileReference: fileReference, fileName: requiredFileName, previousFileReference: optionalPreviousFileReference, shouldResetDiff: shouldResetDiff, preview: optionalPreview) diff --git a/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Step.swift b/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Step.swift index 625e16572f..78cf270b80 100644 --- a/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Step.swift +++ b/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Step.swift @@ -46,7 +46,7 @@ public final class Step: Semantic, DirectiveConvertible { self.caption = caption } - public convenience init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { precondition(directive.name == Step.directiveName) _ = Semantic.Analyses.HasOnlyKnownArguments(severityIfFound: .warning, allowedArguments: []).analyze(directive, children: directive.children, source: source, problems: &problems) @@ -55,10 +55,10 @@ public final class Step: Semantic, DirectiveConvertible { var remainder: MarkupContainer let optionalMedia: (any Media)? - (optionalMedia, remainder) = Semantic.Analyses.HasExactlyOneMedia(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: bundle, problems: &problems) + (optionalMedia, remainder) = Semantic.Analyses.HasExactlyOneMedia(severityIfNotFound: nil).analyze(directive, children: directive.children, source: source, for: inputs, problems: &problems) let optionalCode: Code? - (optionalCode, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (optionalCode, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) let paragraphs: [Paragraph] (paragraphs, remainder) = Semantic.Analyses.ExtractAllMarkup().analyze(directive, children: remainder, source: source, problems: &problems) diff --git a/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Steps.swift b/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Steps.swift index 9edba4a4cb..96da81f3c9 100644 --- a/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Steps.swift +++ b/Sources/SwiftDocC/Semantics/Tutorial/Tasks/Steps/Steps.swift @@ -34,7 +34,7 @@ public final class Steps: Semantic, DirectiveConvertible { self.content = content } - public convenience init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { precondition(directive.name == Steps.directiveName) _ = Semantic.Analyses.HasOnlyKnownArguments(severityIfFound: .warning, allowedArguments: []) @@ -46,7 +46,7 @@ public final class Steps: Semantic, DirectiveConvertible { let stepsContent: [Semantic] = directive.children.compactMap { child -> Semantic? in if let directive = child as? BlockDirective, directive.name == Step.directiveName { - return Step(from: directive, source: source, for: bundle, problems: &problems) + return Step(from: directive, source: source, for: inputs, problems: &problems) } else { return MarkupContainer(child) } diff --git a/Sources/SwiftDocC/Semantics/Tutorial/Tasks/TutorialSection.swift b/Sources/SwiftDocC/Semantics/Tutorial/Tasks/TutorialSection.swift index 17ded53583..d95a3bcecb 100644 --- a/Sources/SwiftDocC/Semantics/Tutorial/Tasks/TutorialSection.swift +++ b/Sources/SwiftDocC/Semantics/Tutorial/Tasks/TutorialSection.swift @@ -77,7 +77,7 @@ public final class TutorialSection: Semantic, DirectiveConvertible, Abstracted, } } - public convenience init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { precondition(directive.name == TutorialSection.directiveName) let arguments = Semantic.Analyses.HasOnlyKnownArguments(severityIfFound: .warning, allowedArguments: [Semantics.Title.argumentName]).analyze(directive, children: directive.children, source: source, problems: &problems) @@ -88,14 +88,14 @@ public final class TutorialSection: Semantic, DirectiveConvertible, Abstracted, var remainder: MarkupContainer let optionalSteps: Steps? - (optionalSteps, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: .warning).analyze(directive, children: directive.children, source: source, for: bundle, problems: &problems) + (optionalSteps, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: .warning).analyze(directive, children: directive.children, source: source, for: inputs, problems: &problems) - Semantic.Analyses.HasOnlySequentialHeadings(severityIfFound: .warning, startingFromLevel: 2).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + Semantic.Analyses.HasOnlySequentialHeadings(severityIfFound: .warning, startingFromLevel: 2).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) let redirects: [Redirect] - (redirects, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (redirects, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) - let content = StackedContentParser.topLevelContent(from: remainder, source: source, for: bundle, problems: &problems) + let content = StackedContentParser.topLevelContent(from: remainder, source: source, for: inputs, problems: &problems) guard let title = requiredTitle else { return nil diff --git a/Sources/SwiftDocC/Semantics/TutorialArticle/TutorialArticle.swift b/Sources/SwiftDocC/Semantics/TutorialArticle/TutorialArticle.swift index 56961cba84..add27734fe 100644 --- a/Sources/SwiftDocC/Semantics/TutorialArticle/TutorialArticle.swift +++ b/Sources/SwiftDocC/Semantics/TutorialArticle/TutorialArticle.swift @@ -102,7 +102,7 @@ public final class TutorialArticle: Semantic, DirectiveConvertible, Abstracted, self.redirects = redirects } - public convenience init?(from directive: BlockDirective, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) { + public convenience init?(from directive: BlockDirective, source: URL?, for inputs: DocumentationContext.Inputs, problems: inout [Problem]) { precondition(directive.name == TutorialArticle.directiveName) let arguments = Semantic.Analyses.HasOnlyKnownArguments(severityIfFound: .warning, allowedArguments: [Semantics.Time.argumentName]) @@ -116,20 +116,20 @@ public final class TutorialArticle: Semantic, DirectiveConvertible, Abstracted, var remainder: MarkupContainer let optionalIntro: Intro? - (optionalIntro, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: .warning).analyze(directive, children: directive.children, source: source, for: bundle, problems: &problems) + (optionalIntro, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: .warning).analyze(directive, children: directive.children, source: source, for: inputs, problems: &problems) - let headings = Semantic.Analyses.HasOnlySequentialHeadings(severityIfFound: .warning, startingFromLevel: 2).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + let headings = Semantic.Analyses.HasOnlySequentialHeadings(severityIfFound: .warning, startingFromLevel: 2).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) - let content = StackedContentParser.topLevelContent(from: remainder, source: source, for: bundle, problems: &problems) + let content = StackedContentParser.topLevelContent(from: remainder, source: source, for: inputs, problems: &problems) let optionalAssessments: Assessments? - (optionalAssessments, remainder) = Semantic.Analyses.HasAtMostOne().analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (optionalAssessments, remainder) = Semantic.Analyses.HasAtMostOne().analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) let optionalCallToActionImage: ImageMedia? - (optionalCallToActionImage, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (optionalCallToActionImage, remainder) = Semantic.Analyses.HasExactlyOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) let redirects: [Redirect] - (redirects, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: bundle, problems: &problems) + (redirects, remainder) = Semantic.Analyses.HasAtLeastOne(severityIfNotFound: nil).analyze(directive, children: remainder, source: source, for: inputs, problems: &problems) self.init(originalMarkup: directive, durationMinutes: optionalTime, intro: optionalIntro, content: content, assessments: optionalAssessments, callToActionImage: optionalCallToActionImage, landmarks: headings, redirects: redirects.isEmpty ? nil : redirects) } @@ -152,7 +152,7 @@ public enum MarkupLayout { } struct StackedContentParser { - static func topLevelContent(from markup: some Sequence, source: URL?, for bundle: DocumentationBundle, problems: inout [Problem]) -> [MarkupLayout] { + static func topLevelContent(from markup: some Sequence, source: URL?, for bundle: DocumentationContext.Inputs, problems: inout [Problem]) -> [MarkupLayout] { return markup.reduce(into: []) { (accumulation, nextBlock) in if let directive = nextBlock as? BlockDirective { if directive.name == Stack.directiveName, diff --git a/Sources/SwiftDocC/SwiftDocC.docc/SwiftDocC/DocumentationContextGroup.md b/Sources/SwiftDocC/SwiftDocC.docc/SwiftDocC/DocumentationContextGroup.md index 32904e973c..39ae956855 100644 --- a/Sources/SwiftDocC/SwiftDocC.docc/SwiftDocC/DocumentationContextGroup.md +++ b/Sources/SwiftDocC/SwiftDocC.docc/SwiftDocC/DocumentationContextGroup.md @@ -24,7 +24,7 @@ let (bundle, dataProvider) = try inputsProvider.inputsAndDataProvider( options: bundleDiscoveryOptions ) -let context = try DocumentationContext(bundle: bundle, dataProvider: dataProvider) +let context = try DocumentationContext(inputs: bundle, dataProvider: dataProvider) ``` ### Accessing Documentation @@ -79,4 +79,4 @@ let sourceFileURL = try context.documentURL(for: reference) - ``CodeColorsPreferenceKey`` - ``SRGBColor`` - + diff --git a/Sources/SwiftDocC/Utility/FeatureFlags.swift b/Sources/SwiftDocC/Utility/FeatureFlags.swift index def7e642d1..b3a90bb331 100644 --- a/Sources/SwiftDocC/Utility/FeatureFlags.swift +++ b/Sources/SwiftDocC/Utility/FeatureFlags.swift @@ -32,9 +32,9 @@ public struct FeatureFlags: Codable { /// Creates a set of feature flags with all default values. public init() {} - /// Set feature flags that were loaded from a bundle's Info.plist. - internal mutating func loadFlagsFromBundle(_ bundleFlags: DocumentationBundle.Info.BundleFeatureFlags) { - if let overloadsPresentation = bundleFlags.experimentalOverloadedSymbolPresentation { + /// Set feature flags that were loaded from an input files Info.plist. + internal mutating func loadFlagsFromInputs(_ inputFilesFlags: DocumentationContext.Inputs.Info.BundleFeatureFlags) { + if let overloadsPresentation = inputFilesFlags.experimentalOverloadedSymbolPresentation { self.isExperimentalOverloadedSymbolPresentationEnabled = overloadsPresentation } } diff --git a/Sources/SwiftDocC/Utility/FoundationExtensions/Dictionary+TypedValues.swift b/Sources/SwiftDocC/Utility/FoundationExtensions/Dictionary+TypedValues.swift index 6ca1858aca..34ff43d05c 100644 --- a/Sources/SwiftDocC/Utility/FoundationExtensions/Dictionary+TypedValues.swift +++ b/Sources/SwiftDocC/Utility/FoundationExtensions/Dictionary+TypedValues.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -53,7 +53,7 @@ enum TypedValueError: DescribedError { /// The requested value is of the wrong type. case wrongType(key: String, expected: Any.Type, actual: Any.Type) /// One or more required ``DocumentationBundle.Info.Key``s are missing. - case missingRequiredKeys([DocumentationBundle.Info.CodingKeys]) + case missingRequiredKeys([DocumentationContext.Inputs.Info.CodingKeys]) var errorDescription: String { switch self { diff --git a/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift b/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift index 248dcdc9db..9d97be0640 100644 --- a/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift +++ b/Sources/SwiftDocCTestUtilities/FilesAndFolders.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2021-2024 Apple Inc. and the Swift project authors + Copyright (c) 2021-2025 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -114,14 +114,14 @@ public struct InfoPlist: File, DataRepresentable { } public init(from decoder: any Decoder) throws { - let container = try decoder.container(keyedBy: DocumentationBundle.Info.CodingKeys.self) + let container = try decoder.container(keyedBy: DocumentationContext.Inputs.Info.CodingKeys.self) displayName = try container.decodeIfPresent(String.self, forKey: .displayName) identifier = try container.decodeIfPresent(String.self, forKey: .id) defaultAvailability = try container.decodeIfPresent([String : [DefaultAvailability.ModuleAvailability]].self, forKey: .defaultAvailability) } public func encode(to encoder: any Encoder) throws { - var container = encoder.container(keyedBy: DocumentationBundle.Info.CodingKeys.self) + var container = encoder.container(keyedBy: DocumentationContext.Inputs.Info.CodingKeys.self) try container.encodeIfPresent(displayName, forKey: .displayName) try container.encodeIfPresent(identifier, forKey: .id) try container.encodeIfPresent(defaultAvailability, forKey: .defaultAvailability) diff --git a/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertAction.swift b/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertAction.swift index 6f0af6647c..64bdd9e560 100644 --- a/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertAction.swift +++ b/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertAction.swift @@ -167,7 +167,7 @@ public struct ConvertAction: AsyncAction { } configuration.externalDocumentationConfiguration.dependencyArchives = dependencies - let (bundle, dataProvider) = try signposter.withIntervalSignpost("Discover inputs", id: signposter.makeSignpostID()) { + let (inputs, dataProvider) = try signposter.withIntervalSignpost("Discover inputs", id: signposter.makeSignpostID()) { try DocumentationContext.InputsProvider(fileManager: fileManager) .inputsAndDataProvider( startingPoint: documentationBundleURL, @@ -178,12 +178,12 @@ public struct ConvertAction: AsyncAction { self.configuration = configuration - self.bundle = bundle + self.inputs = inputs self.dataProvider = dataProvider } let configuration: DocumentationContext.Configuration - private let bundle: DocumentationBundle + private let inputs: DocumentationContext.Inputs private let dataProvider: any DataProvider /// A block of extra work that tests perform to affect the time it takes to convert documentation @@ -286,10 +286,10 @@ public struct ConvertAction: AsyncAction { workingDirectory: temporaryFolder, fileManager: fileManager) - let indexer = try Indexer(outputURL: temporaryFolder, bundleID: bundle.id) + let indexer = try Indexer(outputURL: temporaryFolder, bundleID: inputs.id) let registerInterval = signposter.beginInterval("Register", id: signposter.makeSignpostID()) - let context = try await DocumentationContext(bundle: bundle, dataProvider: dataProvider, diagnosticEngine: diagnosticEngine, configuration: configuration) + let context = try await DocumentationContext(inputs: inputs, dataProvider: dataProvider, diagnosticEngine: diagnosticEngine, configuration: configuration) signposter.endInterval("Register", registerInterval) let outputConsumer = ConvertFileWritingConsumer( @@ -300,7 +300,7 @@ public struct ConvertAction: AsyncAction { indexer: indexer, enableCustomTemplates: experimentalEnableCustomTemplates, transformForStaticHostingIndexHTML: transformForStaticHosting ? indexHTML : nil, - bundleID: bundle.id + bundleID: inputs.id ) if experimentalModifyCatalogWithGeneratedCuration, let catalogURL = rootURL { @@ -318,7 +318,7 @@ public struct ConvertAction: AsyncAction { do { conversionProblems = try signposter.withIntervalSignpost("Process") { try ConvertActionConverter.convert( - bundle: bundle, + inputs: inputs, context: context, outputConsumer: outputConsumer, sourceRepository: sourceRepository, @@ -347,7 +347,7 @@ public struct ConvertAction: AsyncAction { let tableOfContentsFilename = CatalogTemplateKind.tutorialTopLevelFilename let source = rootURL?.appendingPathComponent(tableOfContentsFilename) var replacements = [Replacement]() - if let tableOfContentsTemplate = CatalogTemplateKind.tutorialTemplateFiles(bundle.displayName)[tableOfContentsFilename] { + if let tableOfContentsTemplate = CatalogTemplateKind.tutorialTemplateFiles(inputs.displayName)[tableOfContentsFilename] { replacements.append( Replacement( range: .init(line: 1, column: 1, source: source) ..< .init(line: 1, column: 1, source: source), @@ -438,7 +438,7 @@ public struct ConvertAction: AsyncAction { context: context, indexer: nil, transformForStaticHostingIndexHTML: nil, - bundleID: bundle.id + bundleID: inputs.id ) try outputConsumer.consume(benchmarks: Benchmark.main) diff --git a/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertFileWritingConsumer.swift b/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertFileWritingConsumer.swift index 56e4925851..9133d48424 100644 --- a/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertFileWritingConsumer.swift +++ b/Sources/SwiftDocCUtilities/Action/Actions/Convert/ConvertFileWritingConsumer.swift @@ -34,7 +34,7 @@ struct ConvertFileWritingConsumer: ConvertOutputConsumer, ExternalNodeConsumer { indexer: ConvertAction.Indexer?, enableCustomTemplates: Bool = false, transformForStaticHostingIndexHTML: URL?, - bundleID: DocumentationBundle.Identifier? + bundleID: DocumentationContext.Inputs.Identifier? ) { self.targetFolder = targetFolder self.bundleRootFolder = bundleRootFolder @@ -73,7 +73,7 @@ struct ConvertFileWritingConsumer: ConvertOutputConsumer, ExternalNodeConsumer { indexer?.index(externalRenderNode) } - func consume(assetsInBundle bundle: DocumentationBundle) throws { + func consume(assetsInInputs inputs: DocumentationContext.Inputs) throws { func copyAsset(_ asset: DataAsset, to destinationFolder: URL) throws { for sourceURL in asset.variants.values where !sourceURL.isAbsoluteWebURL { let assetName = sourceURL.lastPathComponent @@ -84,7 +84,7 @@ struct ConvertFileWritingConsumer: ConvertOutputConsumer, ExternalNodeConsumer { } } - let bundleID = bundle.id + let bundleID = inputs.id assert(bundleID.rawValue == self.assetPrefixComponent, "Unexpectedly encoding assets for a bundle other than the one this output consumer was created for.") // Create images directory if needed. @@ -129,21 +129,21 @@ struct ConvertFileWritingConsumer: ConvertOutputConsumer, ExternalNodeConsumer { // If the bundle contains a `header.html` file, inject a