-
-
Notifications
You must be signed in to change notification settings - Fork 624
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
Add support for existential type (any) to AutoMockable.stencil #1169
Add support for existential type (any) to AutoMockable.stencil #1169
Conversation
Hello @paul1893 , thank you a lot for your contribution! I would like to ask you to add unit tests to cover failing and successful test, to see if your fix covers all of the new syntax features at once 👍 If needed, I can assist with that, just need some examples what needs to be verified, or a set of data you have applied the template against. Thank you 🙏 |
Hello 👋 protocol StubProtocol {}
// sourcery: AutoMockable
protocol AnyProtocol {
var a: any StubProtocol { get }
var b: (any StubProtocol)? { get }
var c: (any StubProtocol)! { get }
var d: (((any StubProtocol)?) -> Void) { get }
var e: [(any StubProtocol)?] { get }
func f(_ x: (any StubProtocol)?, y: (any StubProtocol)!, z: any StubProtocol)
} If you think about others, don't hesitate. Have you some leads or advice to give me before I start to implement tests ? When looking at the history of AutoMockable.stencil I intended to be inspired by this. |
Hello 👋 I've spent some time tonight to enrich the sample. Here it is: protocol StubProtocol {}
protocol StubWithAnyNameProtocol {}
// sourcery: AutoMockable
protocol AnyProtocol {
var a: any StubProtocol { get }
var b: (any StubProtocol)? { get }
var c: (any StubProtocol)! { get }
var d: (((any StubProtocol)?) -> Void) { get }
var e: [(any StubProtocol)?] { get }
func f(_ x: (any StubProtocol)?, y: (any StubProtocol)!, z: any StubProtocol)
var g: any StubProtocol { get }
var h: (any StubProtocol)? { get }
var i: (any StubProtocol)! { get }
func j(x: (any StubProtocol)?, y: (any StubProtocol)!, z: any StubProtocol) async -> String
func k(x: ((any StubProtocol)?) -> Void, y: (any StubProtocol) -> Void)
func l(x: (((any StubProtocol)?) -> Void), y: ((any StubProtocol) -> Void))
var anyConfusingPropertyName: any StubProtocol { get }
func m(anyConfusingArgumentName: any StubProtocol)
func n(x: @escaping ((any StubProtocol)?) -> Void)
var o: any StubWithAnyNameProtocol { get }
func p(_ x: (any StubWithAnyNameProtocol)?)
} The stencil have basically 4 new macros: I wrote a test to verify everything ok. But I'm still a little bit lost by the project hierarchy, as previously said I tried to add my test into
needs to be changed
So all of this let me think I'm on the wrong track for the test part. Using a side sample app I know my produced output looks like this with the sample above 👆: class AnyProtocolMock: AnyProtocol {
var a: any StubProtocol {
get { return underlyingA }
set(value) { underlyingA = value }
}
var underlyingA: (any StubProtocol)!
var b: (any StubProtocol)?
var c: (any StubProtocol)!
var d: (((any StubProtocol)?) -> Void) {
get { return underlyingD }
set(value) { underlyingD = value }
}
var underlyingD: ((((any StubProtocol)?) -> Void))!
var e: [(any StubProtocol)?] = []
var g: any StubProtocol {
get { return underlyingG }
set(value) { underlyingG = value }
}
var underlyingG: (any StubProtocol)!
var h: (any StubProtocol)?
var i: (any StubProtocol)!
var anyConfusingPropertyName: any StubProtocol {
get { return underlyingAnyConfusingPropertyName }
set(value) { underlyingAnyConfusingPropertyName = value }
}
var underlyingAnyConfusingPropertyName: (any StubProtocol)!
var o: any StubWithAnyNameProtocol {
get { return underlyingO }
set(value) { underlyingO = value }
}
var underlyingO: (any StubWithAnyNameProtocol)!
//MARK: - f
var fyzCallsCount = 0
var fyzCalled: Bool {
return fyzCallsCount > 0
}
var fyzReceivedArguments: (x: (any StubProtocol)?, y: (any StubProtocol)?, z: any StubProtocol)?
var fyzReceivedInvocations: [(x: (any StubProtocol)?, y: (any StubProtocol)?, z: any StubProtocol)] = []
var fyzClosure: (((any StubProtocol)?, (any StubProtocol)?, any StubProtocol) -> Void)?
func f(_ x: (any StubProtocol)?, y: (any StubProtocol)!, z: any StubProtocol) {
fyzCallsCount += 1
fyzReceivedArguments = (x: x, y: y, z: z)
fyzReceivedInvocations.append((x: x, y: y, z: z))
fyzClosure?(x, y, z)
}
//MARK: - j
var jxyzCallsCount = 0
var jxyzCalled: Bool {
return jxyzCallsCount > 0
}
var jxyzReceivedArguments: (x: (any StubProtocol)?, y: (any StubProtocol)?, z: any StubProtocol)?
var jxyzReceivedInvocations: [(x: (any StubProtocol)?, y: (any StubProtocol)?, z: any StubProtocol)] = []
var jxyzReturnValue: String!
var jxyzClosure: (((any StubProtocol)?, (any StubProtocol)?, any StubProtocol) async -> String)?
func j(x: (any StubProtocol)?, y: (any StubProtocol)!, z: any StubProtocol) async -> String {
jxyzCallsCount += 1
jxyzReceivedArguments = (x: x, y: y, z: z)
jxyzReceivedInvocations.append((x: x, y: y, z: z))
if let jxyzClosure = jxyzClosure {
return await jxyzClosure(x, y, z)
} else {
return jxyzReturnValue
}
}
//MARK: - k
var kxyCallsCount = 0
var kxyCalled: Bool {
return kxyCallsCount > 0
}
var kxyClosure: ((((any StubProtocol)?) -> Void, (any StubProtocol) -> Void) -> Void)?
func k(x: ((any StubProtocol)?) -> Void, y: (any StubProtocol) -> Void) {
kxyCallsCount += 1
kxyClosure?(x, y)
}
//MARK: - l
var lxyCallsCount = 0
var lxyCalled: Bool {
return lxyCallsCount > 0
}
var lxyClosure: ((((any StubProtocol)?) -> Void, (any StubProtocol) -> Void) -> Void)?
func l(x: ((any StubProtocol)?) -> Void, y: (any StubProtocol) -> Void) {
lxyCallsCount += 1
lxyClosure?(x, y)
}
//MARK: - m
var mAnyConfusingArgumentNameCallsCount = 0
var mAnyConfusingArgumentNameCalled: Bool {
return mAnyConfusingArgumentNameCallsCount > 0
}
var mAnyConfusingArgumentNameReceivedAnyConfusingArgumentName: (any StubProtocol)?
var mAnyConfusingArgumentNameReceivedInvocations: [(any StubProtocol)] = []
var mAnyConfusingArgumentNameClosure: ((any StubProtocol) -> Void)?
func m(anyConfusingArgumentName: any StubProtocol) {
mAnyConfusingArgumentNameCallsCount += 1
mAnyConfusingArgumentNameReceivedAnyConfusingArgumentName = anyConfusingArgumentName
mAnyConfusingArgumentNameReceivedInvocations.append(anyConfusingArgumentName)
mAnyConfusingArgumentNameClosure?(anyConfusingArgumentName)
}
//MARK: - n
var nxCallsCount = 0
var nxCalled: Bool {
return nxCallsCount > 0
}
var nxReceivedX: ((((any StubProtocol)?) -> Void))?
var nxReceivedInvocations: [((((any StubProtocol)?) -> Void))] = []
var nxClosure: ((@escaping ((any StubProtocol)?) -> Void) -> Void)?
func n(x: @escaping ((any StubProtocol)?) -> Void) {
nxCallsCount += 1
nxReceivedX = x
nxReceivedInvocations.append(x)
nxClosure?(x)
}
//MARK: - p
var pCallsCount = 0
var pCalled: Bool {
return pCallsCount > 0
}
var pReceivedX: (any StubWithAnyNameProtocol)?
var pReceivedInvocations: [(any StubWithAnyNameProtocol)?] = []
var pClosure: (((any StubWithAnyNameProtocol)?) -> Void)?
func p(_ x: (any StubWithAnyNameProtocol)?) {
pCallsCount += 1
pReceivedX = x
pReceivedInvocations.append(x)
pClosure?(x)
}
} which seems correct. |
🙌🏻 Hello @paul1893 , I have checked out your branch and checked all the tests we have, and seems like the tests you have put in place are the right way to verify the new behaviour. @krzysztofzablocki could you please confirm? I'd like this to be merged sooner than later, if possible, since it is a missing functionality, thank you 🙏🏻 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good to me!
Thanks @krzysztofzablocki 👍🏻 Thanks @paul1893 as well 👍🏻 🕵🏻 Seems like we might have introduced a failing test with this PR (but I am unsure). I'll take a look 👀 |
👋🏻 Hey @paul1893 , could you please extrapolate why this change was made: -public protocol AccessLevelProtocol
+protocol AccessLevelProtocol Because that is one of the reasons UTs are failing after this merge. But that's not the only issue - file There's also additional redundancy I could find: -public var underlyingName: String!
+public var underlyingName: (String)! Thank you 🙏🏻 |
Hello 👋
-public protocol AccessLevelProtocol
+protocol AccessLevelProtocol as I tried to explain -protocol StaticMethodProtocol:AutoMockable {
- static func staticFunction(String) -> String
-}
+protocol StaticMethodProtocol: AutoMockable {
+ static func staticFunction(_: String) -> String
+} These changes were introduced only because the compiler complains on my side. 2.)
I noticed that too during my deep dive but seems to be the case before the #1169 merge right ?
Where did you find those ? I couldn't find Thanks |
Context
With Swift 5.6,
any
keyword have been introduced.This allows us to define existential types in Swift by prefixing a type with the
any
keyword. An existential means “any type, but conforming to protocol X.”As reported in #1149 Sourcery does not handle it in the current AutoMockable.stencil
In this PR
I've updated the AutoMockable.stencil to support this new keyword.