Skip to content

Commit 31e6b1c

Browse files
authored
Support resolving links in @DeprecationSummary content (#784) (#789)
1 parent 659dee3 commit 31e6b1c

File tree

3 files changed

+133
-4
lines changed

3 files changed

+133
-4
lines changed

Sources/SwiftDocC/Semantics/ReferenceResolver.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2021-2023 Apple Inc. and the Swift project authors
4+
Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -442,6 +442,9 @@ struct ReferenceResolver: SemanticVisitor {
442442
}
443443
return ParametersSection(parameters: parameters)
444444
}
445+
let newDeprecatedSummaryVariants = symbol.deprecatedSummaryVariants.map {
446+
return DeprecatedSection(content: $0.content.map { visitMarkup($0) })
447+
}
445448
let newDictionaryKeysVariants = symbol.dictionaryKeysSectionVariants.map { dictionaryKeysSection -> DictionaryKeysSection in
446449
let keys = dictionaryKeysSection.dictionaryKeys.map {
447450
DictionaryKey(name: $0.name, contents: $0.contents.map { visitMarkup($0) }, symbol: $0.symbol, required: $0.required)
@@ -485,7 +488,7 @@ struct ReferenceResolver: SemanticVisitor {
485488
externalIDVariants: symbol.externalIDVariants,
486489
accessLevelVariants: symbol.accessLevelVariants,
487490
availabilityVariants: symbol.availabilityVariants,
488-
deprecatedSummaryVariants: symbol.deprecatedSummaryVariants,
491+
deprecatedSummaryVariants: newDeprecatedSummaryVariants,
489492
mixinsVariants: symbol.mixinsVariants,
490493
declarationVariants: symbol.declarationVariants,
491494
defaultImplementationsVariants: symbol.defaultImplementationsVariants,

Tests/SwiftDocCTests/Infrastructure/DocumentationContext/DocumentationContextTests.swift

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2021-2023 Apple Inc. and the Swift project authors
4+
Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -1984,6 +1984,68 @@ let expected = """
19841984
XCTAssertEqual(unmatchedSidecarDiagnostic.severity, .warning)
19851985
}
19861986

1987+
func testDeprecationSummaryWithLocalLink() throws {
1988+
let exampleDocumentation = Folder(name: "unit-test.docc", content: [
1989+
JSONFile(name: "ModuleName.symbols.json", content: makeSymbolGraph(
1990+
moduleName: "ModuleName",
1991+
symbols: ["Old", "New"].map {
1992+
SymbolGraph.Symbol(
1993+
identifier: .init(precise: "\($0.lowercased())-symbol-id", interfaceLanguage: "swift"),
1994+
names: .init(title: "\($0)Symbol", navigator: nil, subHeading: nil, prose: nil),
1995+
pathComponents: ["\($0)Symbol"],
1996+
docComment: nil,
1997+
accessLevel: .public,
1998+
kind: .init(parsedIdentifier: .class, displayName: "Kind Display Name"),
1999+
mixins: [:]
2000+
)
2001+
}
2002+
)),
2003+
2004+
TextFile(name: "Extension.md", utf8Content: """
2005+
# ``OldSymbol``
2006+
2007+
@DeprecationSummary {
2008+
Use ``NewSymbol`` instead.
2009+
}
2010+
2011+
Deprecate a symbol and link to its replacement in the deprecation message.
2012+
"""),
2013+
2014+
TextFile(name: "Article.md", utf8Content: """
2015+
# Article
2016+
2017+
@DeprecationSummary {
2018+
Use ``NewSymbol`` instead.
2019+
}
2020+
2021+
Link to external content in an article deprecation message.
2022+
"""),
2023+
])
2024+
2025+
let tempURL = try createTempFolder(content: [exampleDocumentation])
2026+
let (_, bundle, context) = try loadBundle(from: tempURL)
2027+
2028+
XCTAssert(context.problems.isEmpty, "Unexpected problems:\n\(context.problems.map(\.diagnostic.summary).joined(separator: "\n"))")
2029+
2030+
do {
2031+
let reference = ResolvedTopicReference(bundleIdentifier: bundle.identifier, path: "/documentation/ModuleName/OldSymbol", sourceLanguage: .swift)
2032+
let node = try context.entity(with: reference)
2033+
2034+
let deprecatedSection = try XCTUnwrap((node.semantic as? Symbol)?.deprecatedSummary)
2035+
XCTAssertEqual(deprecatedSection.content.count, 1)
2036+
XCTAssertEqual(deprecatedSection.content.first?.format().trimmingCharacters(in: .whitespaces), "Use ``doc://unit-test/documentation/ModuleName/NewSymbol`` instead.", "The link should have been resolved")
2037+
}
2038+
2039+
do {
2040+
let reference = ResolvedTopicReference(bundleIdentifier: bundle.identifier, path: "/documentation/unit-test/Article", sourceLanguage: .swift)
2041+
let node = try context.entity(with: reference)
2042+
2043+
let deprecatedSection = try XCTUnwrap((node.semantic as? Article)?.deprecationSummary)
2044+
XCTAssertEqual(deprecatedSection.count, 1)
2045+
XCTAssertEqual(deprecatedSection.first?.format().trimmingCharacters(in: .whitespaces), "Use ``doc://unit-test/documentation/ModuleName/NewSymbol`` instead.", "The link should have been resolved")
2046+
}
2047+
}
2048+
19872049
func testUncuratedArticleDiagnostics() throws {
19882050
var unknownSymbolSidecarURL: URL!
19892051

Tests/SwiftDocCTests/Infrastructure/ExternalReferenceResolverTests.swift

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2021-2023 Apple Inc. and the Swift project authors
4+
Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -1005,4 +1005,68 @@ Document @1:1-1:35
10051005
XCTAssertTrue(objCTopicIDs.contains("doc://com.test.external/path/to/external/objCSymbol"))
10061006
XCTAssertFalse(objCTopicIDs.contains("doc://com.test.external/path/to/external/swiftSymbol"))
10071007
}
1008+
1009+
func testDeprecationSummaryWithExternalLink() throws {
1010+
let exampleDocumentation = Folder(name: "unit-test.docc", content: [
1011+
JSONFile(name: "ModuleName.symbols.json", content: makeSymbolGraph(
1012+
moduleName: "ModuleName",
1013+
symbols: [
1014+
SymbolGraph.Symbol(
1015+
identifier: .init(precise: "symbol-id", interfaceLanguage: "swift"),
1016+
names: .init(title: "SymbolName", navigator: nil, subHeading: nil, prose: nil),
1017+
pathComponents: ["SymbolName"],
1018+
docComment: nil,
1019+
accessLevel: .public,
1020+
kind: .init(parsedIdentifier: .class, displayName: "Kind Display Name"),
1021+
mixins: [:]
1022+
)
1023+
]
1024+
)),
1025+
1026+
TextFile(name: "Extension.md", utf8Content: """
1027+
# ``SymbolName``
1028+
1029+
@DeprecationSummary {
1030+
Use <doc://com.external.testbundle/something> instead.
1031+
}
1032+
1033+
Link to external content in a symbol deprecation message.
1034+
"""),
1035+
1036+
TextFile(name: "Article.md", utf8Content: """
1037+
# Article
1038+
1039+
@DeprecationSummary {
1040+
Use <doc://com.external.testbundle/something> instead.
1041+
}
1042+
1043+
Link to external content in an article deprecation message.
1044+
"""),
1045+
])
1046+
1047+
let resolver = TestExternalReferenceResolver()
1048+
1049+
let tempURL = try createTempFolder(content: [exampleDocumentation])
1050+
let (_, bundle, context) = try loadBundle(from: tempURL, externalResolvers: [resolver.bundleIdentifier: resolver])
1051+
1052+
XCTAssert(context.problems.isEmpty, "Unexpected problems:\n\(context.problems.map(\.diagnostic.summary).joined(separator: "\n"))")
1053+
1054+
do {
1055+
let reference = ResolvedTopicReference(bundleIdentifier: bundle.identifier, path: "/documentation/ModuleName/SymbolName", sourceLanguage: .swift)
1056+
let node = try context.entity(with: reference)
1057+
1058+
let deprecatedSection = try XCTUnwrap((node.semantic as? Symbol)?.deprecatedSummary)
1059+
XCTAssertEqual(deprecatedSection.content.count, 1)
1060+
XCTAssertEqual(deprecatedSection.content.first?.format().trimmingCharacters(in: .whitespaces), "Use <doc://com.external.testbundle/externally/resolved/path> instead.", "The link should have been resolved")
1061+
}
1062+
1063+
do {
1064+
let reference = ResolvedTopicReference(bundleIdentifier: bundle.identifier, path: "/documentation/unit-test/Article", sourceLanguage: .swift)
1065+
let node = try context.entity(with: reference)
1066+
1067+
let deprecatedSection = try XCTUnwrap((node.semantic as? Article)?.deprecationSummary)
1068+
XCTAssertEqual(deprecatedSection.count, 1)
1069+
XCTAssertEqual(deprecatedSection.first?.format().trimmingCharacters(in: .whitespaces), "Use <doc://com.external.testbundle/externally/resolved/path> instead.", "The link should have been resolved")
1070+
}
1071+
}
10081072
}

0 commit comments

Comments
 (0)