mutating func referenceFromLink()

in Sources/SwiftDocC/Infrastructure/DocumentationCurator.swift [57:128]


    mutating func referenceFromLink(link: Link, resolved: ResolvedTopicReference, source: URL?) -> ResolvedTopicReference? {
        // Try a link to a topic
        guard let unresolved = link.destination.flatMap(ValidatedURL.init)?
            .requiring(scheme: ResolvedTopicReference.urlScheme)
            .map(UnresolvedTopicReference.init(topicURL:)) else {
                // Emit a warning regarding the invalid link found in a task group.
                problems.append(Problem(diagnostic: Diagnostic(source: source, severity: .warning, range: link.range, identifier: "org.swift.docc.InvalidDocumentationLink", summary: "The link \((link.destination ?? "").singleQuoted) isn't valid", explanation: "Expected a well-formed URL that uses the \(ResolvedTopicReference.urlScheme.singleQuoted) scheme. You can only curate external links in a 'See Also' section."), possibleSolutions: []))
                return nil
        }
        let maybeResolved = context.resolve(.unresolved(unresolved), in: resolved)
        
        if case let .success(resolved) = maybeResolved {
            // The link resolves to a known topic.
            if let node = context.topicGraph.nodeWithReference(resolved) {
                // Make sure to remove any articles that have been registered in the topic graph
                // from the context's uncurated articles
                if node.kind == .article, context.uncuratedArticles.keys.contains(resolved) {
                    context.uncuratedArticles.removeValue(forKey: resolved)
                }
                return resolved
            }
            // The link resolves to a known content section, emit a warning.
            if resolved.fragment != nil, context.nodeAnchorSections.keys.contains(resolved) {
                problems.append(Problem(diagnostic: Diagnostic(source: source, severity: .warning, range: link.range, identifier: "org.swift.docc.SectionCuration", summary: "The content section link \((link.destination ?? "").singleQuoted) isn't allowed in a Topics link group", explanation: "Content sections cannot participate in the documentation hierarchy."), possibleSolutions: []))
                return resolved
            }
        }
        
        // Check if the link has been externally resolved already.
        if let bundleID = unresolved.topicURL.components.host,
           context.externalReferenceResolvers[bundleID] != nil || context.fallbackReferenceResolvers[bundleID] != nil {
            if case .success(let resolvedExternalReference) = context.externallyResolvedLinks[unresolved.topicURL] {
                return resolvedExternalReference
            } else {
                return nil // This link has already failed to resolve.
            }
        }
        
        // Try extracting an article from the cache
        let articleFilename = unresolved.topicURL.components.path.components(separatedBy: "/").last!
        let sourceArticlePath = NodeURLGenerator.Path.article(bundleName: bundle.displayName, articleName: articleFilename).stringValue
        
        let reference = ResolvedTopicReference(
            bundleIdentifier: resolved.bundleIdentifier,
            path: sourceArticlePath,
            sourceLanguages: resolved.sourceLanguages)
        
        guard let currentArticle = self.context.uncuratedArticles[reference],
            let documentationNode = try? DocumentationNode(reference: reference, article: currentArticle.value) else { return nil }
        
        // An article has been found which needs to be extracted from the article cache
        // and curated under the current symbol. To do this we need to re-create the reference
        // to include the current module, update the file location map, and create a new
        // documentation node with the new reference and new semantic article.
        
        // Add reference in the file location map
        context.documentLocationMap[currentArticle.source] = reference
        
        // Add the curated node to the topic graph
        let node = currentArticle.topicGraphNode
        let curatedNode = TopicGraph.Node(reference: reference, kind: node.kind, source: node.source, title: node.title)
        context.topicGraph.addNode(curatedNode)
        
        // Move the article from the article cache to the documentation
        context.documentationCache[reference] = documentationNode
        for anchor in documentationNode.anchorSections {
            context.nodeAnchorSections[anchor.reference] = anchor
        }
        context.uncuratedArticles.removeValue(forKey: reference)
        
        return reference
    }