typealiased / mockingbird

A Swifty mocking framework for Swift and Objective-C.
https://mockingbirdswift.com
MIT License
657 stars 82 forks source link

Generated file is missing imports from transitively inherited protocols #268

Open juyan opened 2 years ago

juyan commented 2 years ago

New Issue Checklist

Overview

It looks like the generated mock file's import only contains some implicit imports, plus the imports from the target being generated. It does not include the imports required from dependent modules.

Example

Swift Package "Base":

import Combine

public protocol BaseProtocol {
    var versionUpdates: AnyPublisher<Int, Never> { get } 
}

Swift Package "Middle":

public protocol MiddleProtocol: BaseProtocol {
    func getFoo() -> Int
}

Now run mockingbird on package Middle with the following command. Note that we have copied BaseProtocol.swift under the MockingbirdSupport folder.

mockingbird generate --project project.json --output-dir Tests/MiddleTests --targets Middle --support ~/Downloads/MockingbirdSupport

Note that generated mock file is like following:

@testable import Middle
@testable import Mockingbird
import Foundation
import Base
import Swift

And the compiler complains that

Cannot find type 'AnyPublisher' in scope

Expected Behavior

Generated mock file should contain this line and should be able to compile

import Combine

Environment

andrewchang-bird commented 2 years ago

Thanks for reporting, Jun. As a workaround you can explicitly import Combine in the file that declares MiddleProtocol and it should correctly resolve the imports.

juyan commented 2 years ago

@andrewchang-bird Thanks.

Could we add supporting file's imports into the generated mock file in order to fix this? By looking at the code it leads me to this line. Wonder if this could be a straightforward fix.

andrewchang-bird commented 2 years ago

That would definitely work, although it’d be ideal to constrain the import list so that importing a new module in an unrelated file doesn’t trigger a recompilation.

MockableType exposes the property inheritedTypes, which we could use here. We need to accumulate all the imports from both the inherited types plus base raw type file imports while building the MockableType and finally use that in FileGenerator.

Let me know if you’d be interested in adding the transitive import handling (it should be a good small/starter task) and I can give you additional pointers or help walk you through it.

juyan commented 2 years ago

Thanks @andrewchang-bird for the pointer.

Definitely interested, but I will get back to you when I have time to look into this.