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

Commit 002b060

Browse files
committed
Refactor initial ad-hoc implementation into formalized relationships.
For the initial version of swift-doc, the relationships between symbols are determined in the process of generating documentation. This lack of separation between model and view concerns leads to unnecessary duplication across multiple tools, overcomplicated view logic, and other unfortunate consequences. This commit refactors that original implementation to create a first-class Relationship object, whose values are constructed once during module initialization.
1 parent aea7f90 commit 002b060

39 files changed

+736
-780
lines changed

Sources/SwiftDoc/API.swift

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import SwiftSemantics
2+
3+
public protocol API: Declaration {
4+
var attributes: [Attribute] { get }
5+
var modifiers: [Modifier] { get }
6+
var name: String { get }
7+
}
8+
9+
// MARK: -
10+
11+
extension API {
12+
public var nonAccessModifiers: [Modifier] {
13+
return modifiers.filter { modifier in
14+
switch modifier.name {
15+
case "private", "fileprivate", "internal", "public", "open":
16+
return false
17+
default:
18+
return true
19+
}
20+
}
21+
}
22+
}
23+
24+
// MARK: -
25+
26+
extension AssociatedType: API {}
27+
extension Class: API {}
28+
extension Enumeration: API {}
29+
extension Enumeration.Case: API {}
30+
31+
extension Function: API {
32+
public var name: String {
33+
return "\(identifier)(\(signature.input.map { ($0.firstName ?? "_") + ":" }.joined()))"
34+
}
35+
}
36+
37+
extension Initializer: API {
38+
public var name: String {
39+
return "\(keyword)\(optional ? "?": "")(\(parameters.map { ($0.firstName ?? "_") + ":" }.joined()))"
40+
}
41+
}
42+
43+
extension Operator: API {}
44+
extension PrecedenceGroup: API {}
45+
extension Protocol: API {}
46+
47+
extension Structure: API {}
48+
49+
extension Subscript: API {
50+
public var name: String {
51+
return "\(keyword)(\(indices.map { ($0.firstName ?? "_") + ":" }.joined()))"
52+
}
53+
}
54+
55+
extension Typealias: API {}
56+
extension Variable: API {}

Sources/SwiftDoc/CompilationCondition.swift

+12
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,15 @@ public struct CompilationCondition: Hashable, Codable {
1010
self.branch = branch
1111
}
1212
}
13+
14+
// MARK: - CustomStringConvertible
15+
16+
extension CompilationCondition: CustomStringConvertible {
17+
public var description: String {
18+
if let condition = branch.condition {
19+
return condition
20+
} else {
21+
return branch.condition ?? "!(\(block.branches.compactMap { $0.condition }.map { "(\($0))"}.joined(separator: "&&")))"
22+
}
23+
}
24+
}

Sources/SwiftDoc/Extensions/Foundation+Extensions.swift

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
import Foundation
22

3+
// MARK: - FileHandle
4+
5+
extension FileHandle: TextOutputStream {
6+
public func write(_ string: String) {
7+
guard let data = string.data(using: .utf8) else { return }
8+
write(data)
9+
}
10+
}
11+
12+
// MARK: - URL
13+
314
extension URL {
4-
func path(relativeTo another: URL) -> String {
15+
public func path(relativeTo another: URL) -> String {
516
let pathComponents = self.pathComponents, otherPathComponents = another.pathComponents
617
guard pathComponents.starts(with: otherPathComponents) else { return path }
718
return pathComponents.suffix(pathComponents.count - otherPathComponents.count).joined(separator: "/")
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,17 @@
11
import SwiftSemantics
22

3-
public protocol API: Declaration {
4-
var attributes: [Attribute] { get }
5-
var keyword: String { get }
6-
var context: String? { get }
7-
var name: String { get }
8-
var isPublic: Bool { get }
3+
public protocol Generic {
4+
var genericParameters: [GenericParameter] { get }
5+
var genericRequirements: [GenericRequirement] { get }
96
}
107

11-
extension API {
12-
public var qualifiedName: String {
13-
guard let context = context else { return name }
14-
return "\(context).\(name)"
15-
}
16-
17-
public func hash(into hasher: inout Hasher) {
18-
switch self {
19-
case let api as AssociatedType:
20-
hasher.combine(api)
21-
case let api as Class:
22-
hasher.combine(api)
23-
case let api as Enumeration:
24-
hasher.combine(api)
25-
case let api as Enumeration.Case:
26-
hasher.combine(api)
27-
case let api as Function:
28-
hasher.combine(api)
29-
case let api as Initializer:
30-
hasher.combine(api)
31-
case let api as Operator:
32-
hasher.combine(api)
33-
case let api as PrecedenceGroup:
34-
hasher.combine(api)
35-
case let api as Protocol:
36-
hasher.combine(api)
37-
case let api as Structure:
38-
hasher.combine(api)
39-
case let api as Subscript:
40-
hasher.combine(api)
41-
case let api as Typealias:
42-
hasher.combine(api)
43-
case let api as Variable:
44-
hasher.combine(api)
45-
default:
46-
assertionFailure("unhandled type: \(self)")
47-
return
48-
}
49-
}
50-
}
51-
52-
public func ==(lhs: API, rhs: API) -> Bool {
53-
switch (lhs, rhs) {
54-
case let (lhs, rhs) as (AssociatedType, AssociatedType):
55-
return lhs == rhs
56-
case let (lhs, rhs) as (Class, Class):
57-
return lhs == rhs
58-
case let (lhs, rhs) as (Enumeration, Enumeration):
59-
return lhs == rhs
60-
case let (lhs, rhs) as (Enumeration.Case, Enumeration.Case):
61-
return lhs == rhs
62-
case let (lhs, rhs) as (Function, Function):
63-
return lhs == rhs
64-
case let (lhs, rhs) as (Initializer, Initializer):
65-
return lhs == rhs
66-
case let (lhs, rhs) as (Operator, Operator):
67-
return lhs == rhs
68-
case let (lhs, rhs) as (PrecedenceGroup, PrecedenceGroup):
69-
return lhs == rhs
70-
case let (lhs, rhs) as (Protocol, Protocol):
71-
return lhs == rhs
72-
case let (lhs, rhs) as (Structure, Structure):
73-
return lhs == rhs
74-
case let (lhs, rhs) as (Subscript, Subscript):
75-
return lhs == rhs
76-
case let (lhs, rhs) as (Typealias, Typealias):
77-
return lhs == rhs
78-
case let (lhs, rhs) as (Variable, Variable):
79-
return lhs == rhs
80-
default:
81-
return false
82-
}
83-
}
84-
85-
extension AssociatedType: API {}
86-
87-
extension Class: API {}
88-
89-
extension Enumeration: API {}
90-
91-
extension Enumeration.Case: API {
92-
public var isPublic: Bool { return true }
93-
}
94-
95-
extension Function: API {
96-
public var name: String {
97-
"\(identifier)(\(signature.input.map { ($0.firstName ?? "_") + ":" }.joined()))"
98-
}
99-
}
100-
101-
extension Initializer: API {
102-
public var name: String {
103-
"\(keyword)\(optional ? "?": "")(\(parameters.map { ($0.firstName ?? "_") + ":" }.joined()))"
104-
}
105-
}
106-
107-
extension Operator: API {
108-
public var isPublic: Bool { return true }
109-
}
110-
111-
extension PrecedenceGroup: API {
112-
public var context: String? { return nil }
113-
}
114-
115-
extension Protocol: API {
116-
public var context: String? { return nil }
117-
}
118-
119-
extension Structure: API {}
120-
121-
extension Subscript: API {
122-
public var name: String {
123-
"\(keyword)(\(indices.map { ($0.firstName ?? "_") + ":" }.joined()))"
124-
}
125-
}
126-
127-
extension Typealias: API {}
128-
129-
extension Variable: API {}
130-
131-
// MARK: -
132-
133-
public protocol Modifiable: Declaration {
134-
var modifiers: [Modifier] { get }
135-
}
136-
137-
extension AssociatedType: Modifiable {}
138-
extension Class: Modifiable {}
139-
extension Enumeration: Modifiable {}
140-
extension Extension: Modifiable {}
141-
extension Function: Modifiable {}
142-
extension Initializer: Modifiable {}
143-
extension PrecedenceGroup: Modifiable {}
144-
extension Protocol: Modifiable {}
145-
extension Structure: Modifiable {}
146-
extension Subscript: Modifiable {}
147-
extension Typealias: Modifiable {}
148-
extension Variable: Modifiable {}
149-
150-
extension Modifiable {
151-
public var isPublic: Bool {
152-
return modifiers.contains { $0.name == "public" || $0.name == "open" }
153-
}
154-
}
8+
extension Class: Generic {}
9+
extension Enumeration: Generic {}
10+
extension Function: Generic {}
11+
extension Initializer: Generic {}
12+
extension Structure: Generic {}
13+
extension Subscript: Generic {}
14+
extension Typealias: Generic {}
15515

15616
// MARK: -
15717

@@ -164,3 +24,6 @@ extension Class: Type {}
16424
extension Enumeration: Type {}
16525
extension Protocol: Type {}
16626
extension Structure: Type {}
27+
extension Unknown: Type {
28+
public var inheritance: [String] { return [] }
29+
}

Sources/SwiftDoc/Identifier.swift

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
public struct Identifier: Hashable {
2+
public let pathComponents: [String]
3+
public let name: String
4+
5+
public func matches(_ string: String) -> Bool {
6+
(pathComponents + CollectionOfOne(name)).reversed().starts(with: string.split(separator: ".").map { String($0) }.reversed())
7+
}
8+
}
9+
10+
// MARK: - CustomStringConvertible
11+
12+
extension Identifier: CustomStringConvertible {
13+
public var description: String {
14+
(pathComponents + CollectionOfOne(name)).joined(separator: ".")
15+
}
16+
}

0 commit comments

Comments
 (0)