diff --git a/Changelog.md b/Changelog.md
index 2ed05c0e..856c6650 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
+- Fixed links to type declarations.
+ #277 by @Lukas-Stuehrk.
- Fixed bug that caused operator implementations to appear in the documentation
although they should be omitted because of their lower access level.
#264 by @Lukas-Stuehrk
diff --git a/Sources/swift-doc/Subcommands/Generate.swift b/Sources/swift-doc/Subcommands/Generate.swift
index a209218c..5e69e4aa 100644
--- a/Sources/swift-doc/Subcommands/Generate.swift
+++ b/Sources/swift-doc/Subcommands/Generate.swift
@@ -74,7 +74,7 @@ extension SwiftDoc {
case is Class, is Enumeration, is Structure, is Protocol:
pages[route(for: symbol)] = TypePage(module: module, symbol: symbol, baseURL: baseURL, includingChildren: symbolFilter)
case let `typealias` as Typealias:
- pages[route(for: `typealias`.name)] = TypealiasPage(module: module, symbol: symbol, baseURL: baseURL)
+ pages[route(for: `typealias`.name)] = TypealiasPage(module: module, symbol: symbol, baseURL: baseURL, includingOtherSymbols: symbolFilter)
case is Operator:
let operatorPage = OperatorPage(module: module, symbol: symbol, baseURL: baseURL, includingImplementations: symbolFilter)
if !operatorPage.implementations.isEmpty {
@@ -97,11 +97,11 @@ extension SwiftDoc {
symbolsByExternalType[extensionDeclaration.extendedType, default: []] += [symbol]
}
for (typeName, symbols) in symbolsByExternalType {
- pages[route(for: typeName)] = ExternalTypePage(module: module, externalType: typeName, symbols: symbols, baseURL: baseURL)
+ pages[route(for: typeName)] = ExternalTypePage(module: module, externalType: typeName, symbols: symbols, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
for (name, symbols) in globals {
- pages[route(for: name)] = GlobalPage(module: module, name: name, symbols: symbols, baseURL: baseURL)
+ pages[route(for: name)] = GlobalPage(module: module, name: name, symbols: symbols, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
guard !pages.isEmpty else {
diff --git a/Sources/swift-doc/Supporting Types/Components/Declaration.swift b/Sources/swift-doc/Supporting Types/Components/Declaration.swift
index d17e6ad3..95f52f0d 100644
--- a/Sources/swift-doc/Supporting Types/Components/Declaration.swift
+++ b/Sources/swift-doc/Supporting Types/Components/Declaration.swift
@@ -10,11 +10,13 @@ struct Declaration: Component {
var symbol: Symbol
var module: Module
let baseURL: String
+ let symbolFilter: (Symbol) -> Bool
- init(of symbol: Symbol, in module: Module, baseURL: String) {
+ init(of symbol: Symbol, in module: Module, baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
self.symbol = symbol
self.module = module
self.baseURL = baseURL
+ self.symbolFilter = symbolFilter
}
// MARK: - Component
@@ -30,9 +32,11 @@ struct Declaration: Component {
var html: HypertextLiteral.HTML {
let code = symbol.declaration.map { $0.html }.joined()
+ let html = linkTypes(of: code, for: symbol, in: module, with: baseURL, includingSymbols: symbolFilter)
+
return #"""
-
\#(unsafeUnescaped: code)
+
\#(unsafeUnescaped: html)
"""#
}
diff --git a/Sources/swift-doc/Supporting Types/Components/Documentation.swift b/Sources/swift-doc/Supporting Types/Components/Documentation.swift
index 3bc07fe0..ec272b1a 100644
--- a/Sources/swift-doc/Supporting Types/Components/Documentation.swift
+++ b/Sources/swift-doc/Supporting Types/Components/Documentation.swift
@@ -11,11 +11,13 @@ struct Documentation: Component {
var symbol: Symbol
var module: Module
let baseURL: String
+ let symbolFilter: (Symbol) -> Bool
- init(for symbol: Symbol, in module: Module, baseURL: String) {
+ init(for symbol: Symbol, in module: Module, baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
self.symbol = symbol
self.module = module
self.baseURL = baseURL
+ self.symbolFilter = symbolFilter
}
// MARK: - Component
@@ -39,7 +41,7 @@ struct Documentation: Component {
Fragment { "\(documentation.summary!.description.escapingEmojiShortcodes)" }
}
- Declaration(of: symbol, in: module, baseURL: baseURL)
+ Declaration(of: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
ForEach(in: documentation.discussionParts) { part in
DiscussionPart(part, for: symbol, in: module, baseURL: baseURL)
@@ -85,7 +87,7 @@ struct Documentation: Component {
var fragments: [HypertextLiteralConvertible] = []
- fragments.append(Declaration(of: symbol, in: module, baseURL: baseURL))
+ fragments.append(Declaration(of: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter))
if let summary = documentation.summary {
fragments.append(#"""
diff --git a/Sources/swift-doc/Supporting Types/Components/Members.swift b/Sources/swift-doc/Supporting Types/Components/Members.swift
index f3aa003a..a64ca7cc 100644
--- a/Sources/swift-doc/Supporting Types/Components/Members.swift
+++ b/Sources/swift-doc/Supporting Types/Components/Members.swift
@@ -9,6 +9,8 @@ struct Members: Component {
var module: Module
let baseURL: String
+ let symbolFilter: (Symbol) -> Bool
+
var members: [Symbol]
var typealiases: [Symbol]
@@ -20,11 +22,13 @@ struct Members: Component {
var genericallyConstrainedMembers: [[GenericRequirement] : [Symbol]]
let defaultImplementations: [Symbol]
- init(of symbol: Symbol, in module: Module, baseURL: String, symbolFilter: (Symbol) -> Bool) {
+ init(of symbol: Symbol, in module: Module, baseURL: String, symbolFilter: @escaping (Symbol) -> Bool) {
self.symbol = symbol
self.module = module
self.baseURL = baseURL
+ self.symbolFilter = symbolFilter
+
self.members = module.interface.members(of: symbol)
.filter { $0.extension?.genericRequirements.isEmpty != false }
.filter(symbolFilter)
@@ -66,7 +70,7 @@ struct Members: Component {
Heading {
Code { member.name }
}
- Documentation(for: member, in: module, baseURL: baseURL)
+ Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
}
}
@@ -83,7 +87,7 @@ struct Members: Component {
Section {
ForEach(in: members) { member in
Heading { member.name }
- Documentation(for: member, in: module, baseURL: baseURL)
+ Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
}
}
@@ -109,7 +113,7 @@ struct Members: Component {
- \#(Documentation(for: member, in: module, baseURL: baseURL).html)
+ \#(Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
"""#
})
@@ -129,7 +133,7 @@ struct Members: Component {
\#(members.map { member -> HypertextLiteral.HTML in
#"""
\#(softbreak(member.name))
- \#(Documentation(for: member, in: module, baseURL: baseURL).html)
+ \#(Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
"""#
})
diff --git a/Sources/swift-doc/Supporting Types/Components/OperatorImplementations.swift b/Sources/swift-doc/Supporting Types/Components/OperatorImplementations.swift
index 124acbf4..0e2af2e0 100644
--- a/Sources/swift-doc/Supporting Types/Components/OperatorImplementations.swift
+++ b/Sources/swift-doc/Supporting Types/Components/OperatorImplementations.swift
@@ -9,13 +9,16 @@ struct OperatorImplementations: Component {
var module: Module
let baseURL: String
+ let symbolFilter: (Symbol) -> Bool
+
var implementations: [Symbol]
- init(of symbol: Symbol, in module: Module, baseURL: String, implementations: [Symbol]) {
+ init(of symbol: Symbol, in module: Module, baseURL: String, implementations: [Symbol], includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
self.symbol = symbol
self.module = module
self.baseURL = baseURL
self.implementations = implementations
+ self.symbolFilter = symbolFilter
}
@@ -29,7 +32,7 @@ struct OperatorImplementations: Component {
Section {
Heading { implementation.name }
- Documentation(for: implementation, in: module, baseURL: baseURL)
+ Documentation(for: implementation, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
}
}
@@ -77,7 +80,7 @@ struct OperatorImplementations: Component {
\#(heading)
\#(unsafeUnescaped: function.genericWhereClause.map({ #"\#($0.escaped)"# }) ?? "")
- \#(Documentation(for: implementation, in: module, baseURL: baseURL).html)
+ \#(Documentation(for: implementation, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
"""#
}
diff --git a/Sources/swift-doc/Supporting Types/Components/Requirements.swift b/Sources/swift-doc/Supporting Types/Components/Requirements.swift
index d7bf8eca..b02c5d37 100644
--- a/Sources/swift-doc/Supporting Types/Components/Requirements.swift
+++ b/Sources/swift-doc/Supporting Types/Components/Requirements.swift
@@ -8,11 +8,13 @@ struct Requirements: Component {
var symbol: Symbol
var module: Module
let baseURL: String
+ let symbolFilter: (Symbol) -> Bool
- init(of symbol: Symbol, in module: Module, baseURL: String) {
+ init(of symbol: Symbol, in module: Module, baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
self.symbol = symbol
self.module = module
self.baseURL = baseURL
+ self.symbolFilter = symbolFilter
}
var sections: [(title: String, requirements: [Symbol])] {
@@ -34,7 +36,7 @@ struct Requirements: Component {
Section {
ForEach(in: section.requirements) { requirement in
Heading { requirement.name.escapingEmojiShortcodes }
- Documentation(for: requirement, in: module, baseURL: baseURL)
+ Documentation(for: requirement, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
}
}
@@ -57,7 +59,7 @@ struct Requirements: Component {
\#(softbreak(member.name))
- \#(Documentation(for: member, in: module, baseURL: baseURL).html)
+ \#(Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
"""#
})
diff --git a/Sources/swift-doc/Supporting Types/Helpers.swift b/Sources/swift-doc/Supporting Types/Helpers.swift
index 31002335..2061b395 100644
--- a/Sources/swift-doc/Supporting Types/Helpers.swift
+++ b/Sources/swift-doc/Supporting Types/Helpers.swift
@@ -20,6 +20,23 @@ public func linkCodeElements(of html: String, for symbol: Symbol, in module: Mod
return document.root?.description ?? html
}
+public func linkTypes(of html: String, for symbol: Symbol, in module: Module, with baseURL: String, includingSymbols symbolFilter: (Symbol) -> Bool) -> String {
+ let document = try! Document(string: html.description)!
+ for element in document.search(xpath: "//span[contains(@class,'type')]") {
+ guard let name = element.content else { continue }
+
+ let candidates = module.interface.symbols(named: "\(symbol.name).\(name)", resolvingTypealiases: true).nonEmpty ?? module.interface.symbols(named: name, resolvingTypealiases: true)
+ if let candidate = candidates.filter(symbolFilter).filter({ $0 != symbol }).first
+ {
+ let a = Element(name: "a")
+ a["href"] = path(for: candidate, with: baseURL)
+ element.wrap(inside: a)
+ }
+ }
+
+ return document.root?.description ?? html
+}
+
public func sidebar(for html: String) -> String {
let toc = Element(name: "ol")
@@ -78,3 +95,9 @@ public func softbreak(_ string: String) -> String {
return regex.stringByReplacingMatches(in: string, options: [], range: NSRange(string.startIndex.. Bool
+
+ init(module: Module, externalType: String, symbols: [Symbol], baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
self.module = module
self.externalType = externalType
self.baseURL = baseURL
+ self.symbolFilter = symbolFilter
self.typealiases = symbols.filter { $0.api is Typealias }
self.initializers = symbols.filter { $0.api is Initializer }
@@ -49,7 +52,7 @@ struct ExternalTypePage: Page {
Heading {
Code { member.name }
}
- Documentation(for: member, in: module, baseURL: baseURL)
+ Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
}
}
@@ -77,7 +80,7 @@ struct ExternalTypePage: Page {
- \#(Documentation(for: member, in: module, baseURL: baseURL).html)
+ \#(Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
"""#
})
diff --git a/Sources/swift-doc/Supporting Types/Pages/GlobalPage.swift b/Sources/swift-doc/Supporting Types/Pages/GlobalPage.swift
index cd8dad0f..bbb599f3 100644
--- a/Sources/swift-doc/Supporting Types/Pages/GlobalPage.swift
+++ b/Sources/swift-doc/Supporting Types/Pages/GlobalPage.swift
@@ -8,12 +8,14 @@ struct GlobalPage: Page {
let name: String
let symbols: [Symbol]
let baseURL: String
+ let symbolFilter: (Symbol) -> Bool
- init(module: Module, name: String, symbols: [Symbol], baseURL: String) {
+ init(module: Module, name: String, symbols: [Symbol], baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
self.module = module
self.name = name
self.symbols = symbols
self.baseURL = baseURL
+ self.symbolFilter = symbolFilter
}
// MARK: - Page
@@ -26,7 +28,7 @@ struct GlobalPage: Page {
return Document {
ForEach(in: symbols) { symbol in
Heading { symbol.id.description }
- Documentation(for: symbol, in: module, baseURL: baseURL)
+ Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
}
}
@@ -48,7 +50,7 @@ struct GlobalPage: Page {
\#(symbols.map { symbol in
- Documentation(for: symbol, in: module, baseURL: baseURL).html
+ Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html
})
"""#
}
diff --git a/Sources/swift-doc/Supporting Types/Pages/OperatorPage.swift b/Sources/swift-doc/Supporting Types/Pages/OperatorPage.swift
index 740e7829..2d979c5d 100644
--- a/Sources/swift-doc/Supporting Types/Pages/OperatorPage.swift
+++ b/Sources/swift-doc/Supporting Types/Pages/OperatorPage.swift
@@ -8,13 +8,15 @@ struct OperatorPage: Page {
let symbol: Symbol
let implementations: [Symbol]
let baseURL: String
+ let symbolFilter: (Symbol) -> Bool
- init(module: Module, symbol: Symbol, baseURL: String, includingImplementations symbolFilter: (Symbol) -> Bool) {
+ init(module: Module, symbol: Symbol, baseURL: String, includingImplementations symbolFilter: @escaping (Symbol) -> Bool) {
precondition(symbol.api is Operator)
self.module = module
self.symbol = symbol
self.implementations = module.interface.functionsByOperator[symbol]?.filter(symbolFilter).sorted() ?? []
self.baseURL = baseURL
+ self.symbolFilter = symbolFilter
}
// MARK: - Page
@@ -27,7 +29,7 @@ struct OperatorPage: Page {
return CommonMark.Document {
Heading { symbol.id.description }
- Documentation(for: symbol, in: module, baseURL: baseURL)
+ Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
}
@@ -38,8 +40,8 @@ struct OperatorPage: Page {
\#(softbreak(symbol.id.description))
- \#(Documentation(for: symbol, in: module, baseURL: baseURL).html)
- \#(OperatorImplementations(of: symbol, in: module, baseURL: baseURL, implementations: implementations).html)
+ \#(Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
+ \#(OperatorImplementations(of: symbol, in: module, baseURL: baseURL, implementations: implementations, includingOtherSymbols: symbolFilter).html)
"""#
}
}
diff --git a/Sources/swift-doc/Supporting Types/Pages/TypePage.swift b/Sources/swift-doc/Supporting Types/Pages/TypePage.swift
index 345acefb..62dbe115 100644
--- a/Sources/swift-doc/Supporting Types/Pages/TypePage.swift
+++ b/Sources/swift-doc/Supporting Types/Pages/TypePage.swift
@@ -27,10 +27,10 @@ struct TypePage: Page {
return CommonMark.Document {
Heading { symbol.id.description }
- Documentation(for: symbol, in: module, baseURL: baseURL)
+ Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
Relationships(of: symbol, in: module, baseURL: baseURL, includingChildren: symbolFilter)
Members(of: symbol, in: module, baseURL: baseURL, symbolFilter: symbolFilter)
- Requirements(of: symbol, in: module, baseURL: baseURL)
+ Requirements(of: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
}
@@ -41,10 +41,10 @@ struct TypePage: Page {
\#(softbreak(symbol.id.description))
- \#(Documentation(for: symbol, in: module, baseURL: baseURL).html)
+ \#(Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
\#(Relationships(of: symbol, in: module, baseURL: baseURL, includingChildren: symbolFilter).html)
\#(Members(of: symbol, in: module, baseURL: baseURL, symbolFilter: symbolFilter).html)
- \#(Requirements(of: symbol, in: module, baseURL: baseURL).html)
+ \#(Requirements(of: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
"""#
}
}
diff --git a/Sources/swift-doc/Supporting Types/Pages/TypealiasPage.swift b/Sources/swift-doc/Supporting Types/Pages/TypealiasPage.swift
index 4c806727..305e14a2 100644
--- a/Sources/swift-doc/Supporting Types/Pages/TypealiasPage.swift
+++ b/Sources/swift-doc/Supporting Types/Pages/TypealiasPage.swift
@@ -7,12 +7,14 @@ struct TypealiasPage: Page {
let module: Module
let symbol: Symbol
let baseURL: String
+ let symbolFilter: (Symbol) -> Bool
- init(module: Module, symbol: Symbol, baseURL: String) {
+ init(module: Module, symbol: Symbol, baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
precondition(symbol.api is Typealias)
self.module = module
self.symbol = symbol
self.baseURL = baseURL
+ self.symbolFilter = symbolFilter
}
// MARK: - Page
@@ -24,7 +26,7 @@ struct TypealiasPage: Page {
var document: CommonMark.Document {
Document {
Heading { symbol.id.description }
- Documentation(for: symbol, in: module, baseURL: baseURL)
+ Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
}
}
@@ -35,7 +37,7 @@ struct TypealiasPage: Page {
\#(softbreak(symbol.id.description))
- \#(Documentation(for: symbol, in: module, baseURL: baseURL).html)
+ \#(Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
"""#
}
}