Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Naming conflicts for types used in extensions from different Frameworks #184

Closed
torstenlehmann opened this issue Apr 4, 2019 · 2 comments

Comments

@torstenlehmann
Copy link

A -> B -> D
A -> C -> D

Framework B:

enum TrackingEvent {
    case tappedButton
}
extension Tracker {
    func track(event: TrackingEvent) {}
}

Framework C:

enum TrackingEvent {
    case tappedButton
}
extension Tracker {
    func track(event: TrackingEvent) {}
}

Framework D:

//sourcery: AutoMockable
protocol Tracker {}

What I do:
I try to generate mocks for A by including all files from A, B, C, D.

What I get:
Naming conflicts in the generated mocks file, because TrackingEvent is not prefixed with the Swift module name.

Workaround:
Prefixing the extension methods argument type with module name:

extension Tracker {
    func track(event: C.TrackingEvent) {}
}

What I want:
Auto prefixes (module name) for all types to prevent naming conflicts. Without them the tool is quite fragile at least for our purposes, but it's very powerful if it works!

@amichnia
Copy link
Collaborator

amichnia commented Apr 4, 2019

@torstenlehmann Thanks for raising. This is, unfortunately, a big conceptual problem, as we don't have module information in general when generating mocks (that's why we still have to declare imports in yml instead of deriving them from types modules).

There are some bigger changes coming in 4.0, and maybe we will find a way to work it out. The big problem is, in general:

  • you have your protocols you gonna mock usually split among separate files
  • the Mocks.generated.swift is a single file

This setup is fragile by default, as it's vulnerable to naming conflicts. If it was possible, I would just namespace mocks based on their module anyway, but this is unfortunately impossible. I see some options though:

  1. If we have knowledge about origin modules for every type, then we can typealias Type = Module.Type in the scope of every mock generated
  2. We will give better support for 'one generated file per mock' or 'per module' approach

The second option seems easier to achieve at this point and does not conflict with the other approach anyway. The 1 might not be possible to be done automatically, but there should be at least possibility to specify these rules in config.

As another workaround, you can use inline mocking:

https://cdn.rawgit.com/MakeAWishFoundation/SwiftyMocky/3.2.0/docs/setup-in-project.html

That will allow you to keep control over file and it's imports and part of the mock definition. You can then either:

  1. Typealias TrackingEvent = C. TrackingEvent
  2. or just not import B in the first place

It's not convenient, so I would try to come with some better solution.

@g-amichnia
Copy link
Collaborator

g-amichnia commented Jul 24, 2020

It is now possible to "annotate" Mock with:

//sourcery: typealias = "A = ModuleName.A"

That would generate proper typelias definition inside mock implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants