Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store only the resolved reference in DocumentationContext.symbolIndex #543

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions Sources/SwiftDocC/Infrastructure/CoverageDataEntry.swift
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) 2021 Apple Inc. and the Swift project authors
Copyright (c) 2021-2023 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 Down Expand Up @@ -371,9 +371,7 @@ extension CoverageDataEntry {
)
let total = children.count
let documented = children.filter {
(context.symbolIndex[$0.reference.description]?.semantic as? Symbol)?
.abstractSection
!= nil
(context.nodeWithSymbolIdentifier($0.reference.description)?.semantic as? Symbol)?.abstractSection != nil
}.count

if total == 0 {
Expand Down
71 changes: 42 additions & 29 deletions Sources/SwiftDocC/Infrastructure/DocumentationContext.swift

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ final class DocumentationCacheBasedLinkResolver {
/// Method called when walking the symbol url tree that checks if a parent of a symbol has had its
/// path modified during loading the symbol graph. If that's the case the method replaces
/// `reference` with an updated reference with a correct reference path.
func updateNodeWithReferenceIfCollisionChild(_ reference: ResolvedTopicReference, symbolsURLHierarchy: inout BidirectionalTree<ResolvedTopicReference>, symbolIndex: inout [String: DocumentationNode], context: DocumentationContext) throws {
func updateNodeWithReferenceIfCollisionChild(_ reference: ResolvedTopicReference, symbolsURLHierarchy: inout BidirectionalTree<ResolvedTopicReference>, symbolIndex: inout [String: ResolvedTopicReference], context: DocumentationContext) throws {
let newReference = try currentReferenceFor(reference: reference, symbolsURLHierarchy: &symbolsURLHierarchy)
guard newReference != reference else { return }

Expand All @@ -523,7 +523,7 @@ final class DocumentationCacheBasedLinkResolver {
// Rewrite the symbol index
if let symbolIdentifier = documentationNode?.symbol?.identifier {
symbolIndex.removeValue(forKey: symbolIdentifier.precise)
symbolIndex[symbolIdentifier.precise] = documentationNode
symbolIndex[symbolIdentifier.precise] = newReference
}

// Replace the topic graph node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ private extension PathHierarchy.Node {
if let fragments = symbol[mixin: SymbolGraph.Symbol.DeclarationFragments.self]?.declarationFragments {
return fragments.map(\.spelling).joined().split(whereSeparator: { $0.isWhitespace || $0.isNewline }).joined(separator: " ")
}
return context.symbolIndex[symbol.identifier.precise]!.name.description
return context.nodeWithSymbolIdentifier(symbol.identifier.precise)!.name.description
}
// This only gets called for PathHierarchy error messages, so hierarchyBasedLinkResolver is never nil.
let reference = context.hierarchyBasedLinkResolver!.resolvedReferenceMap[identifier]!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ final class PathHierarchyBasedLinkResolver {
}

/// Map the resolved identifiers to resolved topic references for all symbols in the given symbol index.
func addMappingForSymbols(symbolIndex: [String: DocumentationNode]) {
func addMappingForSymbols(symbolIndex: [String: ResolvedTopicReference]) {
for (id, node) in pathHierarchy.lookup {
guard let symbol = node.symbol, let node = symbolIndex[symbol.identifier.precise] else {
guard let symbol = node.symbol, let reference = symbolIndex[symbol.identifier.precise] else {
continue
}
resolvedReferenceMap[id] = node.reference
resolvedReferenceMap[id] = reference
}
}

Expand Down Expand Up @@ -164,9 +164,9 @@ final class PathHierarchyBasedLinkResolver {
}

/// Adds the headings for all symbols in the symbol index to the path hierarchy.
func addAnchorForSymbols(symbolIndex: [String: DocumentationNode]) {
func addAnchorForSymbols(symbolIndex: [String: ResolvedTopicReference], documentationCache: [ResolvedTopicReference: DocumentationNode]) {
for (id, node) in pathHierarchy.lookup {
guard let symbol = node.symbol, let node = symbolIndex[symbol.identifier.precise] else { continue }
guard let symbol = node.symbol, let reference = symbolIndex[symbol.identifier.precise], let node = documentationCache[reference] else { continue }
addAnchors(node.anchorSections, to: id)
}
}
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) 2021-2022 Apple Inc. and the Swift project authors
Copyright (c) 2021-2023 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 Down Expand Up @@ -255,14 +255,15 @@ enum GeneratedDocumentationTopics {
// Check that there is origin information (i.e. the symbol is inherited)
let origin = relationship.mixins[SymbolGraph.Relationship.SourceOrigin.mixinKey] as? SymbolGraph.Relationship.SourceOrigin,
// Resolve the containing type
let parent = context.symbolIndex[relationship.target],
let parent = context.nodeWithSymbolIdentifier(relationship.target),
// Resolve the child
let child = context.symbolIndex[relationship.source],
let child = context.nodeWithSymbolIdentifier(relationship.source),
// Get the child symbol
let childSymbol = child.symbol,
// Get the swift extension data
let extends = childSymbol.mixins[SymbolGraph.Symbol.Swift.Extension.mixinKey] as? SymbolGraph.Symbol.Swift.Extension {
let originSymbol = context.symbolIndex[origin.identifier]?.symbol
let extends = childSymbol.mixins[SymbolGraph.Symbol.Swift.Extension.mixinKey] as? SymbolGraph.Symbol.Swift.Extension
{
let originSymbol = context.nodeWithSymbolIdentifier(origin.identifier)?.symbol

// Add the inherited symbol to the index.
try inheritanceIndex.add(child.reference, to: parent.reference, childSymbol: childSymbol, originDisplayName: origin.displayName, originSymbol: originSymbol, extendedModuleName: extends.extendedModule)
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) 2021-2022 Apple Inc. and the Swift project authors
Copyright (c) 2021-2023 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 Down Expand Up @@ -39,27 +39,29 @@ struct SymbolGraphRelationshipsBuilder {
selector: UnifiedSymbolGraph.Selector,
in bundle: DocumentationBundle,
context: DocumentationContext,
symbolIndex: inout [String: DocumentationNode],
symbolIndex: inout [String: ResolvedTopicReference],
documentationCache: [ResolvedTopicReference: DocumentationNode],
engine: DiagnosticEngine
) {
// Resolve source symbol
guard let implementorNode = symbolIndex[edge.source],
let implementorSymbol = implementorNode.semantic as? Symbol else {
guard let implementorNode = symbolIndex[edge.source].flatMap({ documentationCache[$0] }),
let implementorSymbol = implementorNode.semantic as? Symbol
else {
// The source node for implementation relationship not found.
engine.emit(NodeProblem.notFound(edge.source))
return
}

// Resolve target symbol if possible
let optionalInterfaceNode = symbolIndex[edge.target]
let optionalInterfaceNode = symbolIndex[edge.target].flatMap { documentationCache[$0] }

if optionalInterfaceNode == nil {
// Take the interface language of the target symbol
// or if external - default to the language of the current symbol.
let language = symbolIndex[edge.target]?.reference.sourceLanguage
let language = symbolIndex[edge.target]?.sourceLanguage
?? implementorNode.reference.sourceLanguage

let symbolReference = SymbolReference(edge.target, interfaceLanguage: language, symbol: symbolIndex[edge.target]?.symbol)
let symbolReference = SymbolReference(edge.target, interfaceLanguage: language, symbol: symbolIndex[edge.target].flatMap { documentationCache[$0]?.symbol })
guard let unresolved = UnresolvedTopicReference(symbolReference: symbolReference, bundle: bundle) else {
// The symbol reference format is invalid.
engine.emit(NodeProblem.invalidReference(symbolReference.path))
Expand All @@ -74,9 +76,10 @@ struct SymbolGraphRelationshipsBuilder {
// Find out the parent's title
let parentName: String?

if let reference = symbolIndex[edge.source]?.reference,
let parentNode = try? context.entity(with: reference.removingLastPathComponent()),
let title = (parentNode.semantic as? Symbol)?.title {
if let reference = symbolIndex[edge.source],
let parentNode = try? context.entity(with: reference.removingLastPathComponent()),
let title = (parentNode.semantic as? Symbol)?.title
{
parentName = title
} else {
parentName = nil
Expand All @@ -93,14 +96,14 @@ struct SymbolGraphRelationshipsBuilder {
)

// Make the implementation a child of the requirement
guard let childReference = symbolIndex[edge.source]?.reference else {
guard let childReference = symbolIndex[edge.source] else {
// The child wasn't found, invalid reference in relationship.
engine.emit(SymbolGraphRelationshipsBuilder.NodeProblem.notFound(edge.source))
return
}

if let child = context.topicGraph.nodeWithReference(childReference),
let targetReference = symbolIndex[edge.target]?.reference,
let targetReference = symbolIndex[edge.target],
let parent = context.topicGraph.nodeWithReference(targetReference) {
context.topicGraph.addEdge(from: parent, to: child)
}
Expand All @@ -119,30 +122,32 @@ struct SymbolGraphRelationshipsBuilder {
edge: SymbolGraph.Relationship,
selector: UnifiedSymbolGraph.Selector,
in bundle: DocumentationBundle,
symbolIndex: inout [String: DocumentationNode],
symbolIndex: inout [String: ResolvedTopicReference],
documentationCache: [ResolvedTopicReference: DocumentationNode],
engine: DiagnosticEngine
) {
// Resolve source symbol
guard let conformingNode = symbolIndex[edge.source],
let conformingSymbol = conformingNode.semantic as? Symbol else {
// The source node for coformance relationship not found.
guard let conformingNode = symbolIndex[edge.source].flatMap({ documentationCache[$0] }),
let conformingSymbol = conformingNode.semantic as? Symbol
else {
// The source node for conformance relationship not found.
engine.emit(NodeProblem.notFound(edge.source))
return
}

// Resolve target symbol if possible
let optionalConformanceNode = symbolIndex[edge.target]
let optionalConformanceNode = symbolIndex[edge.target].flatMap { documentationCache[$0] }
let conformanceNodeReference: TopicReference

if let conformanceNode = optionalConformanceNode {
conformanceNodeReference = .successfullyResolved(conformanceNode.reference)
} else {
// Take the interface language of the target symbol
// or if external - default to the language of the current symbol.
let language = symbolIndex[edge.target]?.reference.sourceLanguage
let language = symbolIndex[edge.target]?.sourceLanguage
?? conformingNode.reference.sourceLanguage

let symbolReference = SymbolReference(edge.target, interfaceLanguage: language, symbol: symbolIndex[edge.target]?.symbol)
let symbolReference = SymbolReference(edge.target, interfaceLanguage: language, symbol: symbolIndex[edge.target].flatMap { documentationCache[$0]?.symbol })
guard let unresolved = UnresolvedTopicReference(symbolReference: symbolReference, bundle: bundle) else {
// The symbol reference format is invalid.
engine.emit(NodeProblem.invalidReference(symbolReference.path))
Expand Down Expand Up @@ -203,29 +208,32 @@ struct SymbolGraphRelationshipsBuilder {
edge: SymbolGraph.Relationship,
selector: UnifiedSymbolGraph.Selector,
in bundle: DocumentationBundle,
symbolIndex: inout [String: DocumentationNode],
symbolIndex: inout [String: ResolvedTopicReference],
documentationCache: [ResolvedTopicReference: DocumentationNode],
engine: DiagnosticEngine
) {
// Resolve source symbol
guard let childNode = symbolIndex[edge.source],
let childSymbol = childNode.semantic as? Symbol else {
guard let childNode = symbolIndex[edge.source].flatMap({ documentationCache[$0] }),
let childSymbol = childNode.semantic as? Symbol
else {
// The source node for inheritance relationship not found.
engine.emit(NodeProblem.notFound(edge.source))
return
}

// Resolve target symbol if possible
let optionalParentNode = symbolIndex[edge.target]
let optionalParentNode = symbolIndex[edge.target].flatMap { documentationCache[$0] }
let parentNodeReference: TopicReference

if let parentNode = optionalParentNode {
parentNodeReference = .successfullyResolved(parentNode.reference)
} else {
// Use the target symbol language, if external - fallback on child symbol's langauge
let language = symbolIndex[edge.target]?.symbol.map({ SourceLanguage(id: $0.identifier.interfaceLanguage) })
?? childNode.reference.sourceLanguage
// Use the target symbol language, if external - fallback on child symbol's language
let language: SourceLanguage = symbolIndex[edge.target].flatMap {
documentationCache[$0]?.symbol.map({ SourceLanguage(id: $0.identifier.interfaceLanguage) })
} ?? childNode.reference.sourceLanguage

let symbolReference = SymbolReference(edge.target, interfaceLanguage: language, symbol: symbolIndex[edge.target]?.symbol)
let symbolReference = SymbolReference(edge.target, interfaceLanguage: language, symbol: symbolIndex[edge.target].flatMap { documentationCache[$0]?.symbol })
guard let unresolved = UnresolvedTopicReference(symbolReference: symbolReference, bundle: bundle) else {
// The symbol reference format is invalid.
engine.emit(NodeProblem.invalidReference(symbolReference.path))
Expand Down Expand Up @@ -267,14 +275,16 @@ struct SymbolGraphRelationshipsBuilder {
edge: SymbolGraph.Relationship,
selector: UnifiedSymbolGraph.Selector,
in bundle: DocumentationBundle,
symbolIndex: inout [String: DocumentationNode],
symbolIndex: inout [String: ResolvedTopicReference],
documentationCache: [ResolvedTopicReference: DocumentationNode],
engine: DiagnosticEngine
) {
addProtocolRelationship(
edge: edge,
selector: selector,
in: bundle,
symbolIndex: &symbolIndex,
documentationCache: documentationCache,
engine: engine,
required: true
)
Expand All @@ -291,14 +301,16 @@ struct SymbolGraphRelationshipsBuilder {
edge: SymbolGraph.Relationship,
selector: UnifiedSymbolGraph.Selector,
in bundle: DocumentationBundle,
symbolIndex: inout [String: DocumentationNode],
symbolIndex: inout [String: ResolvedTopicReference],
documentationCache: [ResolvedTopicReference: DocumentationNode],
engine: DiagnosticEngine
) {
addProtocolRelationship(
edge: edge,
selector: selector,
in: bundle,
symbolIndex: &symbolIndex,
documentationCache: documentationCache,
engine: engine,
required: false
)
Expand All @@ -316,12 +328,15 @@ struct SymbolGraphRelationshipsBuilder {
edge: SymbolGraph.Relationship,
selector: UnifiedSymbolGraph.Selector,
in bundle: DocumentationBundle,
symbolIndex: inout [String: DocumentationNode],
symbolIndex: inout [String: ResolvedTopicReference],
documentationCache: [ResolvedTopicReference: DocumentationNode],
engine: DiagnosticEngine, required: Bool
) {
// Resolve source symbol
guard let requiredNode = symbolIndex[edge.source],
let requiredSymbol = requiredNode.semantic as? Symbol else {
guard let requiredNodeRef = symbolIndex[edge.source],
let requiredNode = documentationCache[requiredNodeRef],
let requiredSymbol = requiredNode.semantic as? Symbol
else {
// The source node for requirement relationship not found.
engine.emit(NodeProblem.notFound(edge.source))
return
Expand All @@ -341,8 +356,8 @@ struct SymbolGraphRelationshipsBuilder {
static func addInheritedDefaultImplementation(
edge: SymbolGraph.Relationship,
context: DocumentationContext,
symbolIndex: inout [String: DocumentationNode],
moduleName: String,
symbolIndex: inout [String: ResolvedTopicReference],
moduleName: String,
engine: DiagnosticEngine
) {
func setAsInheritedSymbol(origin: SymbolGraph.Relationship.SourceOrigin, for node: inout DocumentationNode, originNode: DocumentationNode?) {
Expand Down Expand Up @@ -374,13 +389,11 @@ struct SymbolGraphRelationshipsBuilder {
// verify we have the matching data in symbolIndex and documentationCache
// and add the origin data to the symbol.
if let origin = edge.mixins[SymbolGraph.Relationship.SourceOrigin.mixinKey] as? SymbolGraph.Relationship.SourceOrigin,
let node = symbolIndex[edge.source],
node.semantic is Symbol,
context.documentationCache.keys.contains(node.reference) {

let reference = symbolIndex[edge.source],
context.documentationCache[reference]?.semantic is Symbol
{
// OK to unwrap - we've verified the existence of the key above.
setAsInheritedSymbol(origin: origin, for: &symbolIndex[edge.source]!, originNode: symbolIndex[origin.identifier])
setAsInheritedSymbol(origin: origin, for: &context.documentationCache[node.reference]!, originNode: symbolIndex[origin.identifier])
setAsInheritedSymbol(origin: origin, for: &context.documentationCache[reference]!, originNode: symbolIndex[origin.identifier].flatMap { context.documentationCache[$0] })
}
}
}
Expand Down
Loading