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
}