mutating func visitDocument()

in Sources/SwiftDocC/Semantics/SemanticAnalyzer.swift [39:100]


    mutating func visitDocument(_ document: Document) -> Semantic? {
        if let range = document.range, range.isEmpty {
            return nil
        }
        
        let semanticChildren = analyzeChildren(of: document)
        let topLevelChildren = semanticChildren.filter {
            return $0 is Technology ||
            $0 is Tutorial ||
            $0 is TutorialArticle
        }

        let topLevelDirectives = BlockDirective.topLevelDirectiveNames
            .map { $0.singleQuoted }
            .list(finalConjunction: .or)
        
        if let source = source {
            if !topLevelChildren.isEmpty, !DocumentationBundleFileTypes.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! 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) {
                // 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,
                    severity: .warning,
                    range: document.range,
                    identifier: "org.swift.docc.missingTopLevelChild",
                    summary: "No valid content was found in this file",
                    explanation: """
                    A '.\(source.pathExtension)' file should contain a top-level directive \
                    (\(topLevelDirectives)) and valid child content. \
                    Only '.md' files support content without a top-level directive
                    """
                )
                problems.append(Problem(diagnostic: diagnostic, possibleSolutions: []))
                return nil
            }
        }
        
        if topLevelChildren.isEmpty {
            guard let article = Article(from: document, source: source, for: bundle, in: context, problems: &problems) else {
                // We've already diagnosed the invalid article.
                return nil
            }
            
            return article
        }
        
        // Diagnose more than one top-level directive
        for extraneousTopLevelChild in topLevelChildren.suffix(from: 1) {
            if let directiveConvertible = extraneousTopLevelChild as? DirectiveConvertible,
                let range = directiveConvertible.originalMarkup.range {
                let diagnostic = Diagnostic(source: source, severity: .warning, range: range, identifier: "org.swift.docc.extraneousTopLevelChild", summary: "Only one top-level directive from \(topLevelDirectives) may exist in a document; this directive will be ignored")
                let solution = Solution(summary: "Remove this extraneous directive", replacements: [Replacement(range: range, replacement: "")])
                problems.append(Problem(diagnostic: diagnostic, possibleSolutions: [solution]))
            }
        }
        return topLevelChildren.first
    }