From 44d04b28b7b375620801f17ef7c549456b97a22d Mon Sep 17 00:00:00 2001 From: Ruslan Alikhamov Date: Tue, 19 Mar 2024 20:49:42 +0400 Subject: [PATCH] Fix Closure Parameter CVarArg with Existential (#1305) * Fixed compilation issue for closures with existential arguments * Added index to MethodParameter * Automatically assign argument name in case it is empty * Add an additional closing parenthesis in case type is a closure with multiple arguments * Disabled implicitly unwrapped optional for return type of a closure * Disabled CVarArg for tuple type * Added new sample for AutoMockable contexts * Updated expected and generated * Support for var arg and "any" keyword * Updated expected and generated code * Updated contexts for AutoMockable * Squashed commit of the following: commit 55da8ed830616479189d8ce5193f1cbcf360372e Author: art-divin Date: Tue Mar 19 15:05:06 2024 +0000 Update Docs commit a8a314d488a8a1bee7b225d611b25c4070c82603 Author: Ruslan Alikhamov Date: Tue Mar 19 18:55:42 2024 +0400 Make AutoMockable Generate Compilable Swift Code (#1304) * Fixed compilation issue for closures with existential arguments * Added index to MethodParameter * Automatically assign argument name in case it is empty * Add an additional closing parenthesis in case type is a closure with multiple arguments * Disabled implicitly unwrapped optional for return type of a closure * Disabled CVarArg for tuple type * Added new sample for AutoMockable contexts * Updated expected and generated * Support for var arg and "any" keyword * Updated expected and generated code * Updated contexts for AutoMockable --- Templates/Templates/AutoMockable.stencil | 5 ++ Templates/Tests/Context/AutoMockable.swift | 27 ++++++-- .../Tests/Context_Linux/AutoMockable.swift | 27 ++++++-- .../Tests/Expected/AutoMockable.expected | 64 +++++++++++++++++++ .../Generated/AutoMockable.generated.swift | 64 +++++++++++++++++++ 5 files changed, 173 insertions(+), 14 deletions(-) diff --git a/Templates/Templates/AutoMockable.stencil b/Templates/Templates/AutoMockable.stencil index c72fda9a4..f1562ec64 100755 --- a/Templates/Templates/AutoMockable.stencil +++ b/Templates/Templates/AutoMockable.stencil @@ -239,6 +239,7 @@ import {{ import }} {{ typeName }} {%- endif -%} {%- endmacro %} +{# Swift does not support closures with variadic parameters of existential types as arguments. That is why existentialClosureVariableTypeName.isVariadic should be false when typeName is a closure #} {% macro existentialClosureVariableTypeName typeName isVariadic keepInout -%} {% set name %} {%- if keepInout -%} @@ -263,6 +264,8 @@ import {{ import }} {{ name | replace:"some","(any" | replace:"?",")?" }} {%- elif typeName|contains:"some " and typeName|contains:"?" -%} {{ name | replace:"some","(any" | replace:"?",")?" }} + {%- elif isVariadic and typeName|contains:"any " -%} + [({{ name }})] {%- elif isVariadic -%} {{ name }}... {%- else -%} @@ -321,6 +324,8 @@ import {{ import }} {{ typeName | replace:"some","(some" | replace:"?",")?" }} {%- elif isVariadic -%} {{ typeName }}... + {%- elif typeName.isClosure and typeName.closure.parameters.count > 0 and typeName.closure.parameters.last.isVariadic -%} + {{ typeName }}) {%- else -%} {{ typeName }} {%- endif -%} diff --git a/Templates/Tests/Context/AutoMockable.swift b/Templates/Tests/Context/AutoMockable.swift index 0e72851be..0678af2cd 100644 --- a/Templates/Tests/Context/AutoMockable.swift +++ b/Templates/Tests/Context/AutoMockable.swift @@ -8,7 +8,11 @@ import Foundation -protocol AutoMockable {} +public protocol AutoMockable {} +protocol StubProtocol {} +protocol StubWithAnyNameProtocol {} +protocol StubWithSomeNameProtocol {} +protocol PersonProtocol {} protocol BasicProtocol: AutoMockable { func loadConfiguration() -> String? @@ -154,9 +158,6 @@ protocol StaticMethodProtocol: AutoMockable { static func staticFunction(_: String) -> String } -protocol StubProtocol {} -protocol StubWithAnyNameProtocol {} - protocol AnyProtocol: AutoMockable { var a: any StubProtocol { get } var b: (any StubProtocol)? { get } @@ -187,8 +188,6 @@ protocol AnyProtocol: AutoMockable { func z() -> any StubProtocol & CustomStringConvertible } -protocol StubWithSomeNameProtocol {} - protocol SomeProtocol: AutoMockable { func a(_ x: (some StubProtocol)?, y: (some StubProtocol)!, z: some StubProtocol) func b(x: (some StubProtocol)?, y: (some StubProtocol)!, z: some StubProtocol) async -> String @@ -197,7 +196,6 @@ protocol SomeProtocol: AutoMockable { func d(_ x: (some StubWithSomeNameProtocol)?) } -protocol PersonProtocol {} class GenericType{} protocol HouseProtocol: AutoMockable { @@ -227,6 +225,21 @@ protocol ExampleVararg { func string(key: String, args: CVarArg...) -> String } +// sourcery: AutoMockable +protocol ExampleVarargTwo { + func toto(args: any StubWithSomeNameProtocol...) +} + +// sourcery: AutoMockable +protocol ExampleVarargThree { + func toto(arg: ((String, any Collection...) -> any Collection)) +} + +// sourcery: AutoMockable +protocol ExampleVarargFour { + func toto(arg: ((String, any Collection...) -> Void)) +} + // sourcery: AutoMockable public protocol ProtocolWithOverrides { func doSomething(_ data: Int) -> [String] diff --git a/Templates/Tests/Context_Linux/AutoMockable.swift b/Templates/Tests/Context_Linux/AutoMockable.swift index 0e72851be..0678af2cd 100644 --- a/Templates/Tests/Context_Linux/AutoMockable.swift +++ b/Templates/Tests/Context_Linux/AutoMockable.swift @@ -8,7 +8,11 @@ import Foundation -protocol AutoMockable {} +public protocol AutoMockable {} +protocol StubProtocol {} +protocol StubWithAnyNameProtocol {} +protocol StubWithSomeNameProtocol {} +protocol PersonProtocol {} protocol BasicProtocol: AutoMockable { func loadConfiguration() -> String? @@ -154,9 +158,6 @@ protocol StaticMethodProtocol: AutoMockable { static func staticFunction(_: String) -> String } -protocol StubProtocol {} -protocol StubWithAnyNameProtocol {} - protocol AnyProtocol: AutoMockable { var a: any StubProtocol { get } var b: (any StubProtocol)? { get } @@ -187,8 +188,6 @@ protocol AnyProtocol: AutoMockable { func z() -> any StubProtocol & CustomStringConvertible } -protocol StubWithSomeNameProtocol {} - protocol SomeProtocol: AutoMockable { func a(_ x: (some StubProtocol)?, y: (some StubProtocol)!, z: some StubProtocol) func b(x: (some StubProtocol)?, y: (some StubProtocol)!, z: some StubProtocol) async -> String @@ -197,7 +196,6 @@ protocol SomeProtocol: AutoMockable { func d(_ x: (some StubWithSomeNameProtocol)?) } -protocol PersonProtocol {} class GenericType{} protocol HouseProtocol: AutoMockable { @@ -227,6 +225,21 @@ protocol ExampleVararg { func string(key: String, args: CVarArg...) -> String } +// sourcery: AutoMockable +protocol ExampleVarargTwo { + func toto(args: any StubWithSomeNameProtocol...) +} + +// sourcery: AutoMockable +protocol ExampleVarargThree { + func toto(arg: ((String, any Collection...) -> any Collection)) +} + +// sourcery: AutoMockable +protocol ExampleVarargFour { + func toto(arg: ((String, any Collection...) -> Void)) +} + // sourcery: AutoMockable public protocol ProtocolWithOverrides { func doSomething(_ data: Int) -> [String] diff --git a/Templates/Tests/Expected/AutoMockable.expected b/Templates/Tests/Expected/AutoMockable.expected index b98c68c8c..5c596bda8 100644 --- a/Templates/Tests/Expected/AutoMockable.expected +++ b/Templates/Tests/Expected/AutoMockable.expected @@ -724,6 +724,70 @@ class ExampleVarargMock: ExampleVararg { } +} +class ExampleVarargFourMock: ExampleVarargFour { + + + + + //MARK: - toto + + var totoArgStringAnyCollectionVoidVoidCallsCount = 0 + var totoArgStringAnyCollectionVoidVoidCalled: Bool { + return totoArgStringAnyCollectionVoidVoidCallsCount > 0 + } + var totoArgStringAnyCollectionVoidVoidClosure: (((String, any Collection...) -> Void) -> Void)? + + func toto(arg: ((String, any Collection...) -> Void)) { + totoArgStringAnyCollectionVoidVoidCallsCount += 1 + totoArgStringAnyCollectionVoidVoidClosure?(arg) + } + + +} +class ExampleVarargThreeMock: ExampleVarargThree { + + + + + //MARK: - toto + + var totoArgStringAnyCollectionAnyCollectionVoidCallsCount = 0 + var totoArgStringAnyCollectionAnyCollectionVoidCalled: Bool { + return totoArgStringAnyCollectionAnyCollectionVoidCallsCount > 0 + } + var totoArgStringAnyCollectionAnyCollectionVoidClosure: (((String, any Collection...) -> any Collection) -> Void)? + + func toto(arg: ((String, any Collection...) -> any Collection)) { + totoArgStringAnyCollectionAnyCollectionVoidCallsCount += 1 + totoArgStringAnyCollectionAnyCollectionVoidClosure?(arg) + } + + +} +class ExampleVarargTwoMock: ExampleVarargTwo { + + + + + //MARK: - toto + + var totoArgsAnyStubWithSomeNameProtocolVoidCallsCount = 0 + var totoArgsAnyStubWithSomeNameProtocolVoidCalled: Bool { + return totoArgsAnyStubWithSomeNameProtocolVoidCallsCount > 0 + } + var totoArgsAnyStubWithSomeNameProtocolVoidReceivedArgs: ([(any StubWithSomeNameProtocol)])? + var totoArgsAnyStubWithSomeNameProtocolVoidReceivedInvocations: [([(any StubWithSomeNameProtocol)])] = [] + var totoArgsAnyStubWithSomeNameProtocolVoidClosure: (([(any StubWithSomeNameProtocol)]) -> Void)? + + func toto(args: any StubWithSomeNameProtocol...) { + totoArgsAnyStubWithSomeNameProtocolVoidCallsCount += 1 + totoArgsAnyStubWithSomeNameProtocolVoidReceivedArgs = args + totoArgsAnyStubWithSomeNameProtocolVoidReceivedInvocations.append(args) + totoArgsAnyStubWithSomeNameProtocolVoidClosure?(args) + } + + } class ExtendableProtocolMock: ExtendableProtocol { diff --git a/Templates/Tests/Generated/AutoMockable.generated.swift b/Templates/Tests/Generated/AutoMockable.generated.swift index b98c68c8c..5c596bda8 100644 --- a/Templates/Tests/Generated/AutoMockable.generated.swift +++ b/Templates/Tests/Generated/AutoMockable.generated.swift @@ -724,6 +724,70 @@ class ExampleVarargMock: ExampleVararg { } +} +class ExampleVarargFourMock: ExampleVarargFour { + + + + + //MARK: - toto + + var totoArgStringAnyCollectionVoidVoidCallsCount = 0 + var totoArgStringAnyCollectionVoidVoidCalled: Bool { + return totoArgStringAnyCollectionVoidVoidCallsCount > 0 + } + var totoArgStringAnyCollectionVoidVoidClosure: (((String, any Collection...) -> Void) -> Void)? + + func toto(arg: ((String, any Collection...) -> Void)) { + totoArgStringAnyCollectionVoidVoidCallsCount += 1 + totoArgStringAnyCollectionVoidVoidClosure?(arg) + } + + +} +class ExampleVarargThreeMock: ExampleVarargThree { + + + + + //MARK: - toto + + var totoArgStringAnyCollectionAnyCollectionVoidCallsCount = 0 + var totoArgStringAnyCollectionAnyCollectionVoidCalled: Bool { + return totoArgStringAnyCollectionAnyCollectionVoidCallsCount > 0 + } + var totoArgStringAnyCollectionAnyCollectionVoidClosure: (((String, any Collection...) -> any Collection) -> Void)? + + func toto(arg: ((String, any Collection...) -> any Collection)) { + totoArgStringAnyCollectionAnyCollectionVoidCallsCount += 1 + totoArgStringAnyCollectionAnyCollectionVoidClosure?(arg) + } + + +} +class ExampleVarargTwoMock: ExampleVarargTwo { + + + + + //MARK: - toto + + var totoArgsAnyStubWithSomeNameProtocolVoidCallsCount = 0 + var totoArgsAnyStubWithSomeNameProtocolVoidCalled: Bool { + return totoArgsAnyStubWithSomeNameProtocolVoidCallsCount > 0 + } + var totoArgsAnyStubWithSomeNameProtocolVoidReceivedArgs: ([(any StubWithSomeNameProtocol)])? + var totoArgsAnyStubWithSomeNameProtocolVoidReceivedInvocations: [([(any StubWithSomeNameProtocol)])] = [] + var totoArgsAnyStubWithSomeNameProtocolVoidClosure: (([(any StubWithSomeNameProtocol)]) -> Void)? + + func toto(args: any StubWithSomeNameProtocol...) { + totoArgsAnyStubWithSomeNameProtocolVoidCallsCount += 1 + totoArgsAnyStubWithSomeNameProtocolVoidReceivedArgs = args + totoArgsAnyStubWithSomeNameProtocolVoidReceivedInvocations.append(args) + totoArgsAnyStubWithSomeNameProtocolVoidClosure?(args) + } + + } class ExtendableProtocolMock: ExtendableProtocol {