Skip to content

Commit

Permalink
Stop using variants storage for HTTP/REST/PropertyList sections (#1104)
Browse files Browse the repository at this point in the history
* Stop using variants storage for HTTP/REST/PropertyList sections

* Fix two new warnings after merging main
  • Loading branch information
d-ronnqvist authored Dec 17, 2024
1 parent a8bcdde commit 890a58d
Show file tree
Hide file tree
Showing 17 changed files with 264 additions and 286 deletions.
34 changes: 16 additions & 18 deletions Sources/SwiftDocC/Infrastructure/DocumentationContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1617,17 +1617,15 @@ public class DocumentationContext {
}
}

let trait = DocumentationDataVariantsTrait(for: selector)

// Merge in all the dictionary keys for each target into their section variants.
keysByTarget.forEach { targetIdentifier, keys in
let target = documentationCache[targetIdentifier]
if let semantic = target?.semantic as? Symbol {
let keys = keys.sorted { $0.name < $1.name }
if semantic.dictionaryKeysSectionVariants[trait] == nil {
semantic.dictionaryKeysSectionVariants[trait] = DictionaryKeysSection(dictionaryKeys: keys)
let keys = keys.sorted(by: \.name)
if semantic.dictionaryKeysSection == nil {
semantic.dictionaryKeysSection = DictionaryKeysSection(dictionaryKeys: keys)
} else {
semantic.dictionaryKeysSectionVariants[trait]?.mergeDictionaryKeys(keys)
semantic.dictionaryKeysSection?.mergeDictionaryKeys(keys)
}
}
}
Expand All @@ -1636,11 +1634,11 @@ public class DocumentationContext {
parametersByTarget.forEach { targetIdentifier, parameters in
let target = documentationCache[targetIdentifier]
if let semantic = target?.semantic as? Symbol {
let parameters = parameters.sorted { $0.name < $1.name }
if semantic.httpParametersSectionVariants[trait] == nil {
semantic.httpParametersSectionVariants[trait] = HTTPParametersSection(parameters: parameters)
let parameters = parameters.sorted(by: \.name)
if semantic.httpParametersSection == nil {
semantic.httpParametersSection = HTTPParametersSection(parameters: parameters)
} else {
semantic.httpParametersSectionVariants[trait]?.mergeParameters(parameters)
semantic.httpParametersSection?.mergeParameters(parameters)
}
}
}
Expand All @@ -1652,12 +1650,12 @@ public class DocumentationContext {
// Add any body parameters to existing body record
var localBody = body
if let identifier = body.symbol?.preciseIdentifier, let bodyParameters = bodyParametersByTarget[identifier] {
localBody.parameters = bodyParameters.sorted { $0.name < $1.name }
localBody.parameters = bodyParameters.sorted(by: \.name)
}
if semantic.httpBodySectionVariants[trait] == nil {
semantic.httpBodySectionVariants[trait] = HTTPBodySection(body: localBody)
if semantic.httpBodySection == nil {
semantic.httpBodySection = HTTPBodySection(body: localBody)
} else {
semantic.httpBodySectionVariants[trait]?.mergeBody(localBody)
semantic.httpBodySection?.mergeBody(localBody)
}
}
}
Expand All @@ -1666,11 +1664,11 @@ public class DocumentationContext {
responsesByTarget.forEach { targetIdentifier, responses in
let target = documentationCache[targetIdentifier]
if let semantic = target?.semantic as? Symbol {
let responses = responses.sorted { $0.statusCode < $1.statusCode }
if semantic.httpResponsesSectionVariants[trait] == nil {
semantic.httpResponsesSectionVariants[trait] = HTTPResponsesSection(responses: responses)
let responses = responses.sorted(by: \.statusCode)
if semantic.httpResponsesSection == nil {
semantic.httpResponsesSection = HTTPResponsesSection(responses: responses)
} else {
semantic.httpResponsesSectionVariants[trait]?.mergeResponses(responses)
semantic.httpResponsesSection?.mergeResponses(responses)
}
}
}
Expand Down
54 changes: 23 additions & 31 deletions Sources/SwiftDocC/Model/DocumentationNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,8 @@ public struct DocumentationNode {
?? .init(availability: [])
}

let endpointVariants = DocumentationDataVariants(
symbolData: unifiedSymbol.mixins,
platformName: platformName
) { mixins -> HTTPEndpointSection? in
if let endpoint = mixins[SymbolGraph.Symbol.HTTP.Endpoint.mixinKey] as? SymbolGraph.Symbol.HTTP.Endpoint {
return HTTPEndpointSection(endpoint: endpoint)
}
return nil
let endpointSection = unifiedSymbol.defaultSymbol?[mixin: SymbolGraph.Symbol.HTTP.Endpoint.self].map { endpoint in
HTTPEndpointSection(endpoint: endpoint)
}

let overloadVariants = DocumentationDataVariants(
Expand Down Expand Up @@ -314,13 +308,13 @@ public struct DocumentationNode {
seeAlsoVariants: .empty,
returnsSectionVariants: .empty,
parametersSectionVariants: .empty,
dictionaryKeysSectionVariants: .empty,
possibleValuesSectionVariants: .empty,
httpEndpointSectionVariants: endpointVariants,
httpBodySectionVariants: .empty,
httpParametersSectionVariants: .empty,
httpResponsesSectionVariants: .empty,
redirectsVariants: .empty,
dictionaryKeysSection: nil,
possibleValuesSection: nil,
httpEndpointSection: endpointSection,
httpBodySection: nil,
httpParametersSection: nil,
httpResponsesSection: nil,
redirects: nil,
crossImportOverlayModule: moduleData.bystanders.map({ (moduleData.name, $0) }),
overloadsVariants: overloadVariants
)
Expand Down Expand Up @@ -399,9 +393,7 @@ public struct DocumentationNode {
semantic.deprecatedSummaryVariants = DocumentationDataVariants(
defaultVariantValue: deprecated
)
semantic.redirectsVariants = DocumentationDataVariants(
defaultVariantValue: documentationExtension?.redirects
)
semantic.redirects = documentationExtension?.redirects

let filter = ParametersAndReturnValidator(diagnosticEngine: engine, docChunkSources: docChunks.map(\.source))
let (parametersSectionVariants, returnsSectionVariants) = filter.makeParametersAndReturnsSections(
Expand All @@ -415,22 +407,22 @@ public struct DocumentationNode {

if let keys = markupModel.discussionTags?.dictionaryKeys, !keys.isEmpty {
// Record the keys extracted from the markdown
semantic.dictionaryKeysSectionVariants[.fallback] = DictionaryKeysSection(dictionaryKeys:keys)
semantic.dictionaryKeysSection = DictionaryKeysSection(dictionaryKeys:keys)
}

if let parameters = markupModel.discussionTags?.httpParameters, !parameters.isEmpty {
// Record the parameters extracted from the markdown
semantic.httpParametersSectionVariants[.fallback] = HTTPParametersSection(parameters: parameters)
semantic.httpParametersSection = HTTPParametersSection(parameters: parameters)
}

if let body = markupModel.discussionTags?.httpBody {
// Record the body extracted from the markdown
semantic.httpBodySectionVariants[.fallback] = HTTPBodySection(body: body)
semantic.httpBodySection = HTTPBodySection(body: body)
}

if let responses = markupModel.discussionTags?.httpResponses, !responses.isEmpty {
// Record the responses extracted from the markdown
semantic.httpResponsesSectionVariants[.fallback] = HTTPResponsesSection(responses: responses)
semantic.httpResponsesSection = HTTPResponsesSection(responses: responses)
}

// The property list symbol's allowed values.
Expand Down Expand Up @@ -467,10 +459,10 @@ public struct DocumentationNode {
}

// Record the possible values extracted from the markdown.
semantic.possibleValuesSectionVariants[.fallback] = PropertyListPossibleValuesSection(possibleValues: knownPossibleValues)
semantic.possibleValuesSection = PropertyListPossibleValuesSection(possibleValues: knownPossibleValues)
} else if let symbolAllowedValues {
// Record the symbol possible values even if none are documented.
semantic.possibleValuesSectionVariants[.fallback] = PropertyListPossibleValuesSection(possibleValues: symbolAllowedValues.value.map {
semantic.possibleValuesSection = PropertyListPossibleValuesSection(possibleValues: symbolAllowedValues.value.map {
PropertyListPossibleValuesSection.PossibleValue(value: String($0), contents: [])
})
}
Expand Down Expand Up @@ -778,13 +770,13 @@ public struct DocumentationNode {
seeAlsoVariants: .init(swiftVariant: markupModel.seeAlsoSection),
returnsSectionVariants: .init(swiftVariant: markupModel.discussionTags.flatMap({ $0.returns.isEmpty ? nil : ReturnsSection(content: $0.returns[0].contents) })),
parametersSectionVariants: .init(swiftVariant: markupModel.discussionTags.flatMap({ $0.parameters.isEmpty ? nil : ParametersSection(parameters: $0.parameters) })),
dictionaryKeysSectionVariants: .init(swiftVariant: markupModel.discussionTags.flatMap({ $0.dictionaryKeys.isEmpty ? nil : DictionaryKeysSection(dictionaryKeys: $0.dictionaryKeys) })),
possibleValuesSectionVariants: .init(swiftVariant: markupModel.discussionTags.flatMap({ $0.possiblePropertyListValues.isEmpty ? nil : PropertyListPossibleValuesSection(possibleValues: $0.possiblePropertyListValues) })),
httpEndpointSectionVariants: .empty,
httpBodySectionVariants: .empty,
httpParametersSectionVariants: .empty,
httpResponsesSectionVariants: .empty,
redirectsVariants: .init(swiftVariant: article?.redirects)
dictionaryKeysSection: markupModel.discussionTags.flatMap({ $0.dictionaryKeys.isEmpty ? nil : DictionaryKeysSection(dictionaryKeys: $0.dictionaryKeys) }),
possibleValuesSection: markupModel.discussionTags.flatMap({ $0.possiblePropertyListValues.isEmpty ? nil : PropertyListPossibleValuesSection(possibleValues: $0.possiblePropertyListValues) }),
httpEndpointSection: nil,
httpBodySection: nil,
httpParametersSection: nil,
httpResponsesSection: nil,
redirects: article?.redirects
)

self.isVirtual = symbol.isVirtual
Expand Down
Original file line number Diff line number Diff line change
@@ -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-2024 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
Expand All @@ -17,18 +17,18 @@ struct DictionaryKeysSectionTranslator: RenderSectionTranslator {
renderNode: inout RenderNode,
renderNodeTranslator: inout RenderNodeTranslator
) -> VariantCollection<CodableContentSection?>? {
translateSectionToVariantCollection(
documentationDataVariants: symbol.dictionaryKeysSectionVariants
) { _, dictionaryKeysSection in
guard !dictionaryKeysSection.dictionaryKeys.isEmpty else { return nil }
// Filter out keys that aren't backed by a symbol
let filteredKeys = dictionaryKeysSection.dictionaryKeys.filter { $0.symbol != nil }
return PropertiesRenderSection(
guard let dictionaryKeysSection = symbol.dictionaryKeysSection,
!dictionaryKeysSection.dictionaryKeys.isEmpty
else { return nil }

// Filter out keys that aren't backed by a symbol
let filteredKeys = dictionaryKeysSection.dictionaryKeys.filter { $0.symbol != nil }

return VariantCollection(defaultValue: CodableContentSection(
PropertiesRenderSection(
title: DictionaryKeysSection.title,
items: filteredKeys.map { renderNodeTranslator.createRenderProperty(name: $0.name, contents: $0.contents, required: $0.required, symbol: $0.symbol) }
)
}
))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,44 @@ struct HTTPBodySectionTranslator: RenderSectionTranslator {
renderNode: inout RenderNode,
renderNodeTranslator: inout RenderNodeTranslator
) -> VariantCollection<CodableContentSection?>? {
translateSectionToVariantCollection(
documentationDataVariants: symbol.httpBodySectionVariants
) { _, httpBodySection -> RenderSection? in
guard let symbol = httpBodySection.body.symbol, let mediaType = httpBodySection.body.mediaType else { return nil }
guard let httpBodySection = symbol.httpBodySection,
let symbol = httpBodySection.body.symbol,
let mediaType = httpBodySection.body.mediaType
else { return nil }

// Filter out parameters that aren't backed by a symbol or don't have a "body" source.
let filteredParameters = httpBodySection.body.parameters.filter { $0.symbol != nil && $0.source == "body" }

let bodyContent = renderNodeTranslator.visitMarkupContainer(
MarkupContainer(httpBodySection.body.contents)
) as! [RenderBlockContent]

let renderedTokens = symbol.declarationFragments?.map { token -> DeclarationRenderSection.Token in
// Create a reference if one found
let reference: ResolvedTopicReference?
if let preciseIdentifier = token.preciseIdentifier,
let resolved = renderNodeTranslator.context.localOrExternalReference(symbolID: preciseIdentifier)
{
reference = resolved

// Add relationship to render references
renderNodeTranslator.collectedTopicReferences.append(resolved)
} else {
reference = nil
}
// Filter out parameters that aren't backed by a symbol or don't have a "body" source.
let filteredParameters = httpBodySection.body.parameters.filter { $0.symbol != nil && $0.source == "body" }

let bodyContent = renderNodeTranslator.visitMarkupContainer(
MarkupContainer(httpBodySection.body.contents)
) as! [RenderBlockContent]

let renderedTokens = symbol.declarationFragments?.map { token -> DeclarationRenderSection.Token in
// Create a reference if one found
let reference: ResolvedTopicReference?
if let preciseIdentifier = token.preciseIdentifier,
let resolved = renderNodeTranslator.context.localOrExternalReference(symbolID: preciseIdentifier)
{
reference = resolved

// Add the declaration token
return DeclarationRenderSection.Token(fragment: token, identifier: reference?.absoluteString)
// Add relationship to render references
renderNodeTranslator.collectedTopicReferences.append(resolved)
} else {
reference = nil
}

return RESTBodyRenderSection(
// Add the declaration token
return DeclarationRenderSection.Token(fragment: token, identifier: reference?.absoluteString)
}

return VariantCollection(defaultValue: CodableContentSection(
RESTBodyRenderSection(
title: "HTTP Body",
mimeType: mediaType,
bodyContentType: renderedTokens ?? [],
content: bodyContent,
parameters: filteredParameters.map { renderNodeTranslator.createRenderProperty(name: $0.name, contents: $0.contents, required: $0.required, symbol: $0.symbol) }
)
}
))
}
}
Original file line number Diff line number Diff line change
@@ -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-2024 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
Expand All @@ -20,30 +20,27 @@ struct HTTPEndpointSectionTranslator: RenderSectionTranslator {
renderNodeTranslator: inout RenderNodeTranslator
) -> VariantCollection<CodableContentSection?>? {
// Check if there is any endpoint available
guard !symbol.httpEndpointSectionVariants.isEmpty else { return nil }
guard let section = symbol.httpEndpointSection else { return nil }

return translateSectionToVariantCollection(
documentationDataVariants: symbol.httpEndpointSectionVariants
) { _, section in
let endpointURL: URL

if endpointType == .production {
endpointURL = section.endpoint.baseURL
} else if let sandboxURL = section.endpoint.sandboxURL {
endpointURL = sandboxURL
} else {
return nil
}
let endpointURL: URL
if endpointType == .production {
endpointURL = section.endpoint.baseURL
} else if let sandboxURL = section.endpoint.sandboxURL {
endpointURL = sandboxURL
} else {
return nil
}

return RESTEndpointRenderSection(
return VariantCollection(defaultValue: CodableContentSection(
RESTEndpointRenderSection(
title: (endpointType == .production ? "URL" : "Sandbox URL"),
tokens: Self.tokensFor(method: section.endpoint.method, baseURL: endpointURL, path: section.endpoint.path)
)
}
))
}

// Generate DeclarationFragments from endpoint data.
static func tokensFor(method: String, baseURL: URL?, path: String) -> [RESTEndpointRenderSection.Token] {
private static func tokensFor(method: String, baseURL: URL?, path: String) -> [RESTEndpointRenderSection.Token] {
var fragments : [RESTEndpointRenderSection.Token] = []
// Operation type

Expand Down
Loading

0 comments on commit 890a58d

Please sign in to comment.