Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit dd19638

Browse files
Lukas-Stuehrkmattt
andauthored
Bring back links to other symbols in declarations (#277)
* Fix the visibility of operator implementations. * Only include operators if they have at least one visible implementation. * Add changelog for #264. * Bring back links to other symbols in declarations. * Refactor the search of linked symbols. * Add changelog entry for #277 Co-authored-by: Mattt <mattt@me.com>
1 parent 6d338d2 commit dd19638

13 files changed

+85
-36
lines changed

Diff for: Changelog.md

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
### Fixed
1919

20+
- Fixed links to type declarations.
21+
#277 by @Lukas-Stuehrk.
2022
- Fixed bug that caused operator implementations to appear in the documentation
2123
although they should be omitted because of their lower access level.
2224
#264 by @Lukas-Stuehrk

Diff for: Sources/swift-doc/Subcommands/Generate.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ extension SwiftDoc {
7474
case is Class, is Enumeration, is Structure, is Protocol:
7575
pages[route(for: symbol)] = TypePage(module: module, symbol: symbol, baseURL: baseURL, includingChildren: symbolFilter)
7676
case let `typealias` as Typealias:
77-
pages[route(for: `typealias`.name)] = TypealiasPage(module: module, symbol: symbol, baseURL: baseURL)
77+
pages[route(for: `typealias`.name)] = TypealiasPage(module: module, symbol: symbol, baseURL: baseURL, includingOtherSymbols: symbolFilter)
7878
case is Operator:
7979
let operatorPage = OperatorPage(module: module, symbol: symbol, baseURL: baseURL, includingImplementations: symbolFilter)
8080
if !operatorPage.implementations.isEmpty {
@@ -97,11 +97,11 @@ extension SwiftDoc {
9797
symbolsByExternalType[extensionDeclaration.extendedType, default: []] += [symbol]
9898
}
9999
for (typeName, symbols) in symbolsByExternalType {
100-
pages[route(for: typeName)] = ExternalTypePage(module: module, externalType: typeName, symbols: symbols, baseURL: baseURL)
100+
pages[route(for: typeName)] = ExternalTypePage(module: module, externalType: typeName, symbols: symbols, baseURL: baseURL, includingOtherSymbols: symbolFilter)
101101
}
102102

103103
for (name, symbols) in globals {
104-
pages[route(for: name)] = GlobalPage(module: module, name: name, symbols: symbols, baseURL: baseURL)
104+
pages[route(for: name)] = GlobalPage(module: module, name: name, symbols: symbols, baseURL: baseURL, includingOtherSymbols: symbolFilter)
105105
}
106106

107107
guard !pages.isEmpty else {

Diff for: Sources/swift-doc/Supporting Types/Components/Declaration.swift

+6-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ struct Declaration: Component {
1010
var symbol: Symbol
1111
var module: Module
1212
let baseURL: String
13+
let symbolFilter: (Symbol) -> Bool
1314

14-
init(of symbol: Symbol, in module: Module, baseURL: String) {
15+
init(of symbol: Symbol, in module: Module, baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
1516
self.symbol = symbol
1617
self.module = module
1718
self.baseURL = baseURL
19+
self.symbolFilter = symbolFilter
1820
}
1921

2022
// MARK: - Component
@@ -30,9 +32,11 @@ struct Declaration: Component {
3032
var html: HypertextLiteral.HTML {
3133
let code = symbol.declaration.map { $0.html }.joined()
3234

35+
let html = linkTypes(of: code, for: symbol, in: module, with: baseURL, includingSymbols: symbolFilter)
36+
3337
return #"""
3438
<div class="declaration">
35-
<pre class="highlight"><code>\#(unsafeUnescaped: code)</code></pre>
39+
<pre class="highlight"><code>\#(unsafeUnescaped: html)</code></pre>
3640
</div>
3741
"""#
3842
}

Diff for: Sources/swift-doc/Supporting Types/Components/Documentation.swift

+5-3
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ struct Documentation: Component {
1111
var symbol: Symbol
1212
var module: Module
1313
let baseURL: String
14+
let symbolFilter: (Symbol) -> Bool
1415

15-
init(for symbol: Symbol, in module: Module, baseURL: String) {
16+
init(for symbol: Symbol, in module: Module, baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
1617
self.symbol = symbol
1718
self.module = module
1819
self.baseURL = baseURL
20+
self.symbolFilter = symbolFilter
1921
}
2022

2123
// MARK: - Component
@@ -39,7 +41,7 @@ struct Documentation: Component {
3941
Fragment { "\(documentation.summary!.description.escapingEmojiShortcodes)" }
4042
}
4143

42-
Declaration(of: symbol, in: module, baseURL: baseURL)
44+
Declaration(of: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
4345

4446
ForEach(in: documentation.discussionParts) { part in
4547
DiscussionPart(part, for: symbol, in: module, baseURL: baseURL)
@@ -85,7 +87,7 @@ struct Documentation: Component {
8587

8688
var fragments: [HypertextLiteralConvertible] = []
8789

88-
fragments.append(Declaration(of: symbol, in: module, baseURL: baseURL))
90+
fragments.append(Declaration(of: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter))
8991

9092
if let summary = documentation.summary {
9193
fragments.append(#"""

Diff for: Sources/swift-doc/Supporting Types/Components/Members.swift

+9-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ struct Members: Component {
99
var module: Module
1010
let baseURL: String
1111

12+
let symbolFilter: (Symbol) -> Bool
13+
1214
var members: [Symbol]
1315

1416
var typealiases: [Symbol]
@@ -20,11 +22,13 @@ struct Members: Component {
2022
var genericallyConstrainedMembers: [[GenericRequirement] : [Symbol]]
2123
let defaultImplementations: [Symbol]
2224

23-
init(of symbol: Symbol, in module: Module, baseURL: String, symbolFilter: (Symbol) -> Bool) {
25+
init(of symbol: Symbol, in module: Module, baseURL: String, symbolFilter: @escaping (Symbol) -> Bool) {
2426
self.symbol = symbol
2527
self.module = module
2628
self.baseURL = baseURL
2729

30+
self.symbolFilter = symbolFilter
31+
2832
self.members = module.interface.members(of: symbol)
2933
.filter { $0.extension?.genericRequirements.isEmpty != false }
3034
.filter(symbolFilter)
@@ -66,7 +70,7 @@ struct Members: Component {
6670
Heading {
6771
Code { member.name }
6872
}
69-
Documentation(for: member, in: module, baseURL: baseURL)
73+
Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
7074
}
7175
}
7276
}
@@ -83,7 +87,7 @@ struct Members: Component {
8387
Section {
8488
ForEach(in: members) { member in
8589
Heading { member.name }
86-
Documentation(for: member, in: module, baseURL: baseURL)
90+
Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
8791
}
8892
}
8993
}
@@ -109,7 +113,7 @@ struct Members: Component {
109113
<h3>
110114
<code><a href=\#("#\(id)")>\#(softbreak(member.name))</a></code>
111115
</h3>
112-
\#(Documentation(for: member, in: module, baseURL: baseURL).html)
116+
\#(Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
113117
</div>
114118
"""#
115119
})
@@ -129,7 +133,7 @@ struct Members: Component {
129133
\#(members.map { member -> HypertextLiteral.HTML in
130134
#"""
131135
<h4>\#(softbreak(member.name))</h4>
132-
\#(Documentation(for: member, in: module, baseURL: baseURL).html)
136+
\#(Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
133137
"""#
134138
})
135139
</section>

Diff for: Sources/swift-doc/Supporting Types/Components/OperatorImplementations.swift

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ struct OperatorImplementations: Component {
99
var module: Module
1010
let baseURL: String
1111

12+
let symbolFilter: (Symbol) -> Bool
13+
1214
var implementations: [Symbol]
1315

14-
init(of symbol: Symbol, in module: Module, baseURL: String, implementations: [Symbol]) {
16+
init(of symbol: Symbol, in module: Module, baseURL: String, implementations: [Symbol], includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
1517
self.symbol = symbol
1618
self.module = module
1719
self.baseURL = baseURL
1820
self.implementations = implementations
21+
self.symbolFilter = symbolFilter
1922
}
2023

2124

@@ -29,7 +32,7 @@ struct OperatorImplementations: Component {
2932
Section {
3033
Heading { implementation.name }
3134

32-
Documentation(for: implementation, in: module, baseURL: baseURL)
35+
Documentation(for: implementation, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
3336
}
3437
}
3538
}
@@ -77,7 +80,7 @@ struct OperatorImplementations: Component {
7780
<a href=\#("#\(id)")>\#(heading)
7881
\#(unsafeUnescaped: function.genericWhereClause.map({ #"<small>\#($0.escaped)</small>"# }) ?? "")</a>
7982
</h3>
80-
\#(Documentation(for: implementation, in: module, baseURL: baseURL).html)
83+
\#(Documentation(for: implementation, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
8184
</div>
8285
"""#
8386
}

Diff for: Sources/swift-doc/Supporting Types/Components/Requirements.swift

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ struct Requirements: Component {
88
var symbol: Symbol
99
var module: Module
1010
let baseURL: String
11+
let symbolFilter: (Symbol) -> Bool
1112

12-
init(of symbol: Symbol, in module: Module, baseURL: String) {
13+
init(of symbol: Symbol, in module: Module, baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
1314
self.symbol = symbol
1415
self.module = module
1516
self.baseURL = baseURL
17+
self.symbolFilter = symbolFilter
1618
}
1719

1820
var sections: [(title: String, requirements: [Symbol])] {
@@ -34,7 +36,7 @@ struct Requirements: Component {
3436
Section {
3537
ForEach(in: section.requirements) { requirement in
3638
Heading { requirement.name.escapingEmojiShortcodes }
37-
Documentation(for: requirement, in: module, baseURL: baseURL)
39+
Documentation(for: requirement, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
3840
}
3941
}
4042
}
@@ -57,7 +59,7 @@ struct Requirements: Component {
5759
<h3>
5860
<code>\#(softbreak(member.name))</code>
5961
</h3>
60-
\#(Documentation(for: member, in: module, baseURL: baseURL).html)
62+
\#(Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
6163
</div>
6264
"""#
6365
})

Diff for: Sources/swift-doc/Supporting Types/Helpers.swift

+23
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,23 @@ public func linkCodeElements(of html: String, for symbol: Symbol, in module: Mod
2020
return document.root?.description ?? html
2121
}
2222

23+
public func linkTypes(of html: String, for symbol: Symbol, in module: Module, with baseURL: String, includingSymbols symbolFilter: (Symbol) -> Bool) -> String {
24+
let document = try! Document(string: html.description)!
25+
for element in document.search(xpath: "//span[contains(@class,'type')]") {
26+
guard let name = element.content else { continue }
27+
28+
let candidates = module.interface.symbols(named: "\(symbol.name).\(name)", resolvingTypealiases: true).nonEmpty ?? module.interface.symbols(named: name, resolvingTypealiases: true)
29+
if let candidate = candidates.filter(symbolFilter).filter({ $0 != symbol }).first
30+
{
31+
let a = Element(name: "a")
32+
a["href"] = path(for: candidate, with: baseURL)
33+
element.wrap(inside: a)
34+
}
35+
}
36+
37+
return document.root?.description ?? html
38+
}
39+
2340
public func sidebar(for html: String) -> String {
2441
let toc = Element(name: "ol")
2542

@@ -78,3 +95,9 @@ public func softbreak(_ string: String) -> String {
7895

7996
return regex.stringByReplacingMatches(in: string, options: [], range: NSRange(string.startIndex..<string.endIndex, in: string), withTemplate: "$1\u{200B}$2")
8097
}
98+
99+
fileprivate extension Collection {
100+
var nonEmpty: Self? {
101+
return isEmpty ? nil : self
102+
}
103+
}

Diff for: Sources/swift-doc/Supporting Types/Pages/ExternalTypePage.swift

+6-3
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ struct ExternalTypePage: Page {
1515
let properties: [Symbol]
1616
let methods: [Symbol]
1717

18-
init(module: Module, externalType: String, symbols: [Symbol], baseURL: String) {
18+
let symbolFilter: (Symbol) -> Bool
19+
20+
init(module: Module, externalType: String, symbols: [Symbol], baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
1921
self.module = module
2022
self.externalType = externalType
2123
self.baseURL = baseURL
24+
self.symbolFilter = symbolFilter
2225

2326
self.typealiases = symbols.filter { $0.api is Typealias }
2427
self.initializers = symbols.filter { $0.api is Initializer }
@@ -49,7 +52,7 @@ struct ExternalTypePage: Page {
4952
Heading {
5053
Code { member.name }
5154
}
52-
Documentation(for: member, in: module, baseURL: baseURL)
55+
Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
5356
}
5457
}
5558
}
@@ -77,7 +80,7 @@ struct ExternalTypePage: Page {
7780
<h3>
7881
<code><a href=\#("#\(id)")>\#(softbreak(member.name))</a></code>
7982
</h3>
80-
\#(Documentation(for: member, in: module, baseURL: baseURL).html)
83+
\#(Documentation(for: member, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
8184
</div>
8285
"""#
8386
})

Diff for: Sources/swift-doc/Supporting Types/Pages/GlobalPage.swift

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ struct GlobalPage: Page {
88
let name: String
99
let symbols: [Symbol]
1010
let baseURL: String
11+
let symbolFilter: (Symbol) -> Bool
1112

12-
init(module: Module, name: String, symbols: [Symbol], baseURL: String) {
13+
init(module: Module, name: String, symbols: [Symbol], baseURL: String, includingOtherSymbols symbolFilter: @escaping (Symbol) -> Bool) {
1314
self.module = module
1415
self.name = name
1516
self.symbols = symbols
1617
self.baseURL = baseURL
18+
self.symbolFilter = symbolFilter
1719
}
1820

1921
// MARK: - Page
@@ -26,7 +28,7 @@ struct GlobalPage: Page {
2628
return Document {
2729
ForEach(in: symbols) { symbol in
2830
Heading { symbol.id.description }
29-
Documentation(for: symbol, in: module, baseURL: baseURL)
31+
Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
3032
}
3133
}
3234
}
@@ -48,7 +50,7 @@ struct GlobalPage: Page {
4850
</h1>
4951
5052
\#(symbols.map { symbol in
51-
Documentation(for: symbol, in: module, baseURL: baseURL).html
53+
Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html
5254
})
5355
"""#
5456
}

Diff for: Sources/swift-doc/Supporting Types/Pages/OperatorPage.swift

+6-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ struct OperatorPage: Page {
88
let symbol: Symbol
99
let implementations: [Symbol]
1010
let baseURL: String
11+
let symbolFilter: (Symbol) -> Bool
1112

12-
init(module: Module, symbol: Symbol, baseURL: String, includingImplementations symbolFilter: (Symbol) -> Bool) {
13+
init(module: Module, symbol: Symbol, baseURL: String, includingImplementations symbolFilter: @escaping (Symbol) -> Bool) {
1314
precondition(symbol.api is Operator)
1415
self.module = module
1516
self.symbol = symbol
1617
self.implementations = module.interface.functionsByOperator[symbol]?.filter(symbolFilter).sorted() ?? []
1718
self.baseURL = baseURL
19+
self.symbolFilter = symbolFilter
1820
}
1921

2022
// MARK: - Page
@@ -27,7 +29,7 @@ struct OperatorPage: Page {
2729
return CommonMark.Document {
2830
Heading { symbol.id.description }
2931

30-
Documentation(for: symbol, in: module, baseURL: baseURL)
32+
Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
3133
}
3234
}
3335

@@ -38,8 +40,8 @@ struct OperatorPage: Page {
3840
<code class="name">\#(softbreak(symbol.id.description))</code>
3941
</h1>
4042
41-
\#(Documentation(for: symbol, in: module, baseURL: baseURL).html)
42-
\#(OperatorImplementations(of: symbol, in: module, baseURL: baseURL, implementations: implementations).html)
43+
\#(Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
44+
\#(OperatorImplementations(of: symbol, in: module, baseURL: baseURL, implementations: implementations, includingOtherSymbols: symbolFilter).html)
4345
"""#
4446
}
4547
}

Diff for: Sources/swift-doc/Supporting Types/Pages/TypePage.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ struct TypePage: Page {
2727
return CommonMark.Document {
2828
Heading { symbol.id.description }
2929

30-
Documentation(for: symbol, in: module, baseURL: baseURL)
30+
Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
3131
Relationships(of: symbol, in: module, baseURL: baseURL, includingChildren: symbolFilter)
3232
Members(of: symbol, in: module, baseURL: baseURL, symbolFilter: symbolFilter)
33-
Requirements(of: symbol, in: module, baseURL: baseURL)
33+
Requirements(of: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter)
3434
}
3535
}
3636

@@ -41,10 +41,10 @@ struct TypePage: Page {
4141
<code class="name">\#(softbreak(symbol.id.description))</code>
4242
</h1>
4343
44-
\#(Documentation(for: symbol, in: module, baseURL: baseURL).html)
44+
\#(Documentation(for: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
4545
\#(Relationships(of: symbol, in: module, baseURL: baseURL, includingChildren: symbolFilter).html)
4646
\#(Members(of: symbol, in: module, baseURL: baseURL, symbolFilter: symbolFilter).html)
47-
\#(Requirements(of: symbol, in: module, baseURL: baseURL).html)
47+
\#(Requirements(of: symbol, in: module, baseURL: baseURL, includingOtherSymbols: symbolFilter).html)
4848
"""#
4949
}
5050
}

0 commit comments

Comments
 (0)