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

Commit 0df8f0a

Browse files
committed
Add resolution for nested types through typealiases
Refactor implementation of ID
1 parent 099ac58 commit 0df8f0a

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

Sources/SwiftDoc/Identifier.swift

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,41 @@
11
public struct Identifier: Hashable {
2-
public let pathComponents: [String]
2+
public let context: [String]
33
public let name: String
4+
public let pathComponents: [String]
5+
6+
public init(context: [String], name: String) {
7+
self.context = context
8+
self.name = name
9+
self.pathComponents = context + CollectionOfOne(name)
10+
}
411

512
public func matches(_ string: String) -> Bool {
6-
(pathComponents + CollectionOfOne(name)).reversed().starts(with: string.split(separator: ".").map { String($0) }.reversed())
13+
return matches(string.split(separator: "."))
14+
}
15+
16+
public func matches(_ pathComponents: [Substring]) -> Bool {
17+
return matches(pathComponents.map(String.init))
18+
}
19+
20+
public func matches(_ pathComponents: [String]) -> Bool {
21+
return self.pathComponents.ends(with: pathComponents)
722
}
823
}
924

1025
// MARK: - CustomStringConvertible
1126

1227
extension Identifier: CustomStringConvertible {
1328
public var description: String {
14-
(pathComponents + CollectionOfOne(name)).joined(separator: ".")
29+
pathComponents.joined(separator: ".")
30+
}
31+
}
32+
33+
fileprivate extension Array {
34+
func ends<PossibleSuffix>(with possibleSuffix: PossibleSuffix) -> Bool
35+
where PossibleSuffix : Sequence,
36+
Self.Element == PossibleSuffix.Element,
37+
Self.Element: Equatable
38+
{
39+
reversed().starts(with: possibleSuffix)
1540
}
1641
}

Sources/SwiftDoc/Interface.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,20 +163,33 @@ public final class Interface {
163163
// MARK: -
164164

165165
public func symbols(named name: String, resolvingTypealiases: Bool) -> [Symbol] {
166+
symbolsGroupedByIdentifier.named(name, resolvingTypealiases: resolvingTypealiases)
167+
}
168+
}
169+
170+
fileprivate extension Dictionary where Key == Identifier, Value == [Symbol] {
171+
func named(_ name: String, resolvingTypealiases: Bool) -> [Symbol] {
166172
var pathComponents: [String] = []
167173
for component in name.split(separator: ".") {
168174
pathComponents.append("\(component)")
169175
guard resolvingTypealiases else { continue }
170176

171-
if let symbols = symbolsGroupedByQualifiedName[pathComponents.joined(separator: ".")],
177+
if let symbols = first(where: { $0.key.pathComponents == pathComponents })?.value,
172178
let symbol = symbols.first(where: { $0.api is Typealias }),
173179
let `typealias` = symbol.api as? Typealias,
174180
let initializedType = `typealias`.initializedType
175181
{
176-
pathComponents = (symbol.context.compactMap { ($0 as? Symbol)?.name ?? ($0 as? Extension)?.extendedType }) + [initializedType]
182+
let initializedTypePathComponents = initializedType.split(separator: ".")
183+
let candidates = keys.filter { $0.matches(initializedTypePathComponents) }
184+
185+
if let id = candidates.max(by: { $0.pathComponents.count > $1.pathComponents.count }) {
186+
pathComponents = id.pathComponents
187+
} else {
188+
return []
189+
}
177190
}
178191
}
179192

180-
return symbolsGroupedByQualifiedName[pathComponents.joined(separator: ".")] ?? []
193+
return first(where: { $0.key.pathComponents == pathComponents })?.value ?? []
181194
}
182195
}

Sources/SwiftDoc/Symbol.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import struct Highlighter.Token
66
public final class Symbol {
77
public typealias ID = Identifier
88

9+
public let id: ID
910
public let api: API
1011
public let context: [Contextual]
1112
public let declaration: [Token]
@@ -19,6 +20,9 @@ public final class Symbol {
1920
public private(set) lazy var conditions: [CompilationCondition] = context.compactMap { $0 as? CompilationCondition }
2021

2122
init(api: API, context: [Contextual], declaration: [Token], documentation: Documentation?, sourceRange: SourceRange?) {
23+
self.id = Identifier(context: context.compactMap {
24+
($0 as? Symbol)?.name ?? ($0 as? Extension)?.extendedType
25+
}, name: api.name)
2226
self.api = api
2327
self.context = context
2428
self.declaration = declaration
@@ -30,12 +34,6 @@ public final class Symbol {
3034
return api.name
3135
}
3236

33-
public private(set) lazy var id: ID = {
34-
Identifier(pathComponents: context.compactMap {
35-
($0 as? Symbol)?.name ?? ($0 as? Extension)?.extendedType
36-
}, name: name)
37-
}()
38-
3937
public var isPublic: Bool {
4038
if api is Unknown {
4139
return true

Tests/SwiftDocTests/InterfaceTypeTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,10 @@ final class InterfaceTypeTests: XCTestCase {
282282
}
283283
284284
public typealias MyClass = SomeClass
285+
286+
public class AnotherClass {
287+
typealias PublicClass = SomeClass
288+
}
285289
286290
public typealias ExternalClass = UIGestureRecognizer
287291
"""#
@@ -306,6 +310,12 @@ final class InterfaceTypeTests: XCTestCase {
306310
XCTAssertEqual(module.interface.symbols(named: "MyClass.InnerObject", resolvingTypealiases: true).first?.name, "InnerObject")
307311
XCTAssertNil(module.interface.symbols(named: "MyClass.InnerObject", resolvingTypealiases: false).first)
308312

313+
XCTAssertEqual(module.interface.symbols(named: "AnotherClass.PublicClass", resolvingTypealiases: true).first?.name, "SomeClass")
314+
XCTAssertTrue(module.interface.symbols(named: "AnotherClass.PublicClass", resolvingTypealiases: false).first?.api is Typealias)
315+
316+
XCTAssertEqual(module.interface.symbols(named: "AnotherClass.PublicClass.ActuallyInternal", resolvingTypealiases: true).first?.name, "InnerStruct")
317+
XCTAssertNil(module.interface.symbols(named: "AnotherClass.PublicClass.ActuallyInternal", resolvingTypealiases: false).first)
318+
309319
XCTAssertNil(module.interface.symbols(named: "ExternalClass", resolvingTypealiases: true).first)
310320
XCTAssertTrue(module.interface.symbols(named: "ExternalClass", resolvingTypealiases: false).first?.api is Typealias)
311321

0 commit comments

Comments
 (0)