krzysztofzablocki / Sourcery

Meta-programming for Swift, stop writing boilerplate code.
http://merowing.info
MIT License
7.58k stars 605 forks source link

Fix associatedtype generics #1345

Closed art-divin closed 1 week ago

art-divin commented 2 weeks ago

Resolves: #1333

Description

This MR introduces a correct way of generating mocks for associatedtype in a protocol marked as AutoMockable.

Context

Previously, Sourcery was not generating a compilable mock if a mockable protocol had associatedtypes used as arguments or return values or types for variables in that protocol.

The reason was both that during processing, protocol's generic requirements for associated types were not stored, and that a protocol was not checked if it had associated type or not.

Now, AutoMockable.stencil contains logic to check if there are both associated types and generic requirements for those types in a protocol or not. Now, if an associated type has a primitive type, and not a protocol, a typealias is injected into the mockable type. When an associated type has a protocol type, then that type is:

Example

Input

//sourcery:AutoMockable
protocol TestProtocol<SomeType> {
    associatedtype SomeType: Sequence where Value.Element: Collection, Value.Element: Hashable, Value.Element: Comparable

    func getValue() -> SomeType

    associatedtype Value2 = Int

    func getValue2() -> Value2
 }

Output

class TestProtocolMock<
    SomeType: Sequence>: TestProtocol
    where SomeType.Element : Collection, SomeType.Element : Hashable, SomeType.Element : Comparable {
    typealias Value2 = Int

    ...
}