Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
20 changes: 8 additions & 12 deletions Sources/SwiftDocC/Infrastructure/DocumentationContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,13 @@ public class DocumentationContext {

insertLandmarks(tutorialArticle.landmarks, from: topicGraphNode, source: url)
} else if let article = analyzed as? Article {

// If the article contains any `@SupportedLanguage` directives in the metadata,
// include those languages in the set of source languages for the reference.
let reference = if let supportedLanguages = article.supportedLanguages {
reference.withSourceLanguages(supportedLanguages)
} else {
reference
}
Comment on lines +834 to +838
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT there's no tests that verify this behavior. If it's needed; can you explain what it's for and add a test that verify that outcome?

// Here we create a topic graph node with the prepared data but we don't add it to the topic graph just yet
// because we don't know where in the hierarchy the article belongs, we will add it later when crawling the manual curation via Topics task groups.
let topicGraphNode = TopicGraph.Node(reference: reference, kind: .article, source: .file(url: url), title: article.title!.plainText)
Expand Down Expand Up @@ -1883,17 +1889,7 @@ public class DocumentationContext {
let path = NodeURLGenerator.pathForSemantic(article.value, source: article.source, bundle: bundle)

// Use the languages specified by the `@SupportedLanguage` directives if present.
let availableSourceLanguages = article.value
.metadata
.flatMap { metadata in
let languages = Set(
metadata.supportedLanguages
.map(\.language)
)

return languages.isEmpty ? nil : languages
}
?? availableSourceLanguages
let availableSourceLanguages = article.value.supportedLanguages ?? availableSourceLanguages

// If available source languages are provided and it contains Swift, use Swift as the default language of
// the article.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ public struct RenderNodeTranslator: SemanticVisitor {
node.hierarchyVariants = hierarchyVariants

// Emit variants only if we're not compiling an article-only catalog to prevent renderers from
// advertising the page as "Swift", which is the language DocC assigns to pages in article only pages.
// advertising the page as "Swift", which is the language DocC assigns to pages in article only catalogs.
// (github.com/swiftlang/swift-docc/issues/240).
if let topLevelModule = context.soleRootModuleReference,
try! context.entity(with: topLevelModule).kind.isSymbol
Expand Down
12 changes: 12 additions & 0 deletions Sources/SwiftDocC/Semantics/Article/Article.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ public final class Article: Semantic, MarkupConvertible, Abstracted, Redirected,
return abstractSection?.paragraph
}

/// The list of supported languages for the article, if present.
///
/// This information is available via `@SupportedLanguage` in the `@Metadata` directive.
public var supportedLanguages: Set<SourceLanguage>? {
guard let metadata = self.metadata else {
return nil
}

let langs = metadata.supportedLanguages.map(\.language)
return langs.isEmpty ? nil : Set(langs)
}

/// An optional custom deprecation summary for a deprecated symbol.
private(set) public var deprecationSummary: MarkupContainer?

Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftDocC/Semantics/Metadata/Metadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public final class Metadata: Semantic, AutomaticDirectiveConvertible {

func validate(source: URL?, problems: inout [Problem]) -> Bool {
// Check that something is configured in the metadata block
if documentationOptions == nil && technologyRoot == nil && displayName == nil && pageImages.isEmpty && customMetadata.isEmpty && callToAction == nil && availability.isEmpty && pageKind == nil && pageColor == nil && titleHeading == nil && redirects == nil && alternateRepresentations.isEmpty {
if documentationOptions == nil && technologyRoot == nil && displayName == nil && pageImages.isEmpty && customMetadata.isEmpty && callToAction == nil && availability.isEmpty && pageKind == nil && pageColor == nil && supportedLanguages.isEmpty && titleHeading == nil && redirects == nil && alternateRepresentations.isEmpty {
let diagnostic = Diagnostic(
source: source,
severity: .information,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5773,6 +5773,44 @@ let expected = """
XCTAssertEqual(solution.replacements.first?.replacement, "")
}

func testSupportedLanguageDirectiveInNonRootArticleWithSymbols() async throws {
let catalog = Folder(name: "unit-test.docc", content: [
TextFile(name: "Root.md", utf8Content: """
# Root

@Metadata {
@TechnologyRoot
@SupportedLanguage(objc)
@SupportedLanguage(data)
}

## Topics

- <doc:Article>
"""),

TextFile(name: "Article.md", utf8Content: """
# Article

@Metadata {
@SupportedLanguage(objc)
@SupportedLanguage(data)
}
"""),
])

let (bundle, context) = try await loadBundle(catalog: catalog)

XCTAssert(context.problems.isEmpty, "Unexpected problems:\n\(context.problems.map(\.diagnostic.summary).joined(separator: "\n"))")

do {
let reference = ResolvedTopicReference(bundleID: bundle.id, path: "/documentation/unit-test/Article", sourceLanguage: .swift)
let node = try context.entity(with: reference)

let supportedLanguages = try XCTUnwrap((node.semantic as? Article)?.metadata?.supportedLanguages)
XCTAssertEqual(supportedLanguages.map(\.language), [.objectiveC, .data])
}
}
}

func assertEqualDumps(_ lhs: String, _ rhs: String, file: StaticString = #filePath, line: UInt = #line) {
Expand Down
22 changes: 22 additions & 0 deletions Tests/SwiftDocCTests/Semantics/ArticleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -249,4 +249,26 @@ class ArticleTests: XCTestCase {
XCTAssertNil(semantic.metadata?.pageKind)
XCTAssertNil(semantic.metadata?.titleHeading)
}

func testSupportedLanguageDirective() async throws {
let source = """
# Root

@Metadata {
@SupportedLanguage(swift)
@SupportedLanguage(objc)
@SupportedLanguage(data)
}
"""
let document = Document(parsing: source, options: [.parseBlockDirectives])
let (bundle, _) = try await testBundleAndContext()
var problems = [Problem]()
let article = Article(from: document, source: nil, for: bundle, problems: &problems)

XCTAssert(problems.isEmpty, "Unexpectedly found problems: \(DiagnosticConsoleWriter.formattedDescription(for: problems))")

XCTAssertNotNil(article)
XCTAssertNotNil(article?.metadata, "Article should have a metadata container since the markup has a @Metadata directive")
XCTAssertEqual(article?.metadata?.supportedLanguages.map(\.language), [.swift, .objectiveC, .data])
}
}