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

Also document default implementations of protocols. #221

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Sources/SwiftDoc/Interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,8 @@ public final class Interface {
public func conditionalCounterparts(of symbol: Symbol) -> [Symbol] {
return symbolsGroupedByIdentifier[symbol.id]?.filter { $0 != symbol }.sorted() ?? []
}

public func defaultImplementations(of symbol: Symbol) -> [Symbol] {
return relationshipsByObject[symbol.id]?.filter { $0.predicate == .defaultImplementationOf }.map { $0.subject }.sorted() ?? []
}
}
7 changes: 5 additions & 2 deletions Sources/swift-doc/Supporting Types/Components/Members.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct Members: Component {
var properties: [Symbol]
var methods: [Symbol]
var genericallyConstrainedMembers: [[GenericRequirement] : [Symbol]]
let defaultImplementations: [Symbol]

init(of symbol: Symbol, in module: Module, baseURL: String, symbolFilter: (Symbol) -> Bool) {
self.symbol = symbol
Expand All @@ -33,6 +34,7 @@ struct Members: Component {
self.properties = members.filter { $0.api is Variable }
self.methods = members.filter { $0.api is Function }
self.genericallyConstrainedMembers = Dictionary(grouping: members) { $0.`extension`?.genericRequirements ?? [] }.filter { !$0.key.isEmpty }
self.defaultImplementations = module.interface.defaultImplementations(of: symbol).filter(symbolFilter)
}

var sections: [(title: String, members: [Symbol])] {
Expand All @@ -41,14 +43,15 @@ struct Members: Component {
("Initializers", initializers),
("Enumeration Cases", cases),
("Properties", properties),
("Methods", methods)
("Methods", methods),
("Default Implementations", defaultImplementations),
].filter { !$0.members.isEmpty }
}

// MARK: - Component

var fragment: Fragment {
guard !members.isEmpty else { return Fragment { "" } }
guard !members.isEmpty || !defaultImplementations.isEmpty else { return Fragment { "" } }

return Fragment {
ForEach(in: sections) { section -> BlockConvertible in
Expand Down
26 changes: 26 additions & 0 deletions Tests/SwiftDocTests/InterfaceTypeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,30 @@ final class InterfaceTypeTests: XCTestCase {
XCTAssertEqual(module.interface.symbols[6].name, "InternalProperties")
XCTAssertEqual(module.interface.symbols[7].name, "internal_prop")
}

func testDefaultImplementationsOfProtocols() throws {
let source = #"""
public protocol SomeProtocol {
func someMethod()
}

public extension SomeProtocol {
func someMethod() { }

func someOtherMethod() { }
}
"""#


let url = try temporaryFile(contents: source)
let sourceFile = try SourceFile(file: url, relativeTo: url.deletingLastPathComponent())
let module = Module(name: "Module", sourceFiles: [sourceFile])

let protocolSymbol = module.interface.symbols[0]
XCTAssertEqual(protocolSymbol.name, "SomeProtocol")
let defaultImplementations = module.interface.defaultImplementations(of: protocolSymbol)
XCTAssertEqual(defaultImplementations.count, 2)
XCTAssertEqual(defaultImplementations[0].name, "someMethod()")
XCTAssertEqual(defaultImplementations[1].name, "someOtherMethod()")
}
}