Skip to content

Commit e8e5595

Browse files
authored
Merge pull request #97 from Matejkob/return-existential
Support returning existential types in functions
2 parents 16f7832 + fbf2d7f commit e8e5595

File tree

4 files changed

+68
-8
lines changed

4 files changed

+68
-8
lines changed

Examples/Sources/ViewModel.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ protocol ServiceProtocol {
1414
func save(name: any Codable, surname: any Codable)
1515
func insert(name: (any Codable)?, surname: (any Codable)?)
1616
func append(name: (any Codable) -> (any Codable)?)
17+
func get() async throws -> any Codable
1718
}
1819

1920
final class ViewModel {

Sources/SpyableMacro/Factories/ReturnValueFactory.swift

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,37 @@ struct ReturnValueFactory {
4242
variablePrefix: String,
4343
functionReturnType: TypeSyntax
4444
) throws -> VariableDeclSyntax {
45-
let typeAnnotation =
46-
if functionReturnType.is(OptionalTypeSyntax.self) {
47-
TypeAnnotationSyntax(type: functionReturnType)
48-
} else {
49-
TypeAnnotationSyntax(
50-
type: ImplicitlyUnwrappedOptionalTypeSyntax(wrappedType: functionReturnType)
45+
/*
46+
func f() -> String?
47+
*/
48+
let typeAnnotation = if functionReturnType.is(OptionalTypeSyntax.self) {
49+
TypeAnnotationSyntax(type: functionReturnType)
50+
/*
51+
func f() -> String!
52+
*/
53+
} else if functionReturnType.is(ImplicitlyUnwrappedOptionalTypeSyntax.self) {
54+
TypeAnnotationSyntax(type: functionReturnType)
55+
/*
56+
func f() -> any Codable
57+
*/
58+
} else if functionReturnType.is(SomeOrAnyTypeSyntax.self) {
59+
TypeAnnotationSyntax(
60+
type: ImplicitlyUnwrappedOptionalTypeSyntax(
61+
wrappedType: TupleTypeSyntax(
62+
elements: TupleTypeElementListSyntax {
63+
TupleTypeElementSyntax(type: functionReturnType)
64+
}
65+
)
5166
)
52-
}
67+
)
68+
/*
69+
func f() -> String
70+
*/
71+
} else {
72+
TypeAnnotationSyntax(
73+
type: ImplicitlyUnwrappedOptionalTypeSyntax(wrappedType: functionReturnType)
74+
)
75+
}
5376

5477
return try VariableDeclSyntax(
5578
"""

Tests/SpyableMacroTests/Factories/UT_ReturnValueFactory.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,22 @@ final class UT_ReturnValueFactory: XCTestCase {
1515
)
1616
}
1717

18-
func testVariableDeclarationOptionType() throws {
18+
func testVariableDeclarationOptionalType() throws {
1919
try assert(
2020
functionReturnType: "String?",
2121
prefixForVariable: "_prefix_",
2222
expectingVariableDeclaration: "var _prefix_ReturnValue: String?"
2323
)
2424
}
2525

26+
func testVariableDeclarationExistentialType() throws {
27+
try assert(
28+
functionReturnType: "any Codable",
29+
prefixForVariable: "_prefix_",
30+
expectingVariableDeclaration: "var _prefix_ReturnValue: (any Codable)!"
31+
)
32+
}
33+
2634
// MARK: Return Statement
2735

2836
func testReturnStatement() {

Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,34 @@ final class UT_SpyFactory: XCTestCase {
319319
)
320320
}
321321

322+
func testDeclarationReturnsExistential() throws {
323+
try assertProtocol(
324+
withDeclaration: """
325+
protocol ServiceProtocol {
326+
func foo() -> any Codable
327+
}
328+
""",
329+
expectingClassDeclaration: """
330+
class ServiceProtocolSpy: ServiceProtocol {
331+
var fooCallsCount = 0
332+
var fooCalled: Bool {
333+
return fooCallsCount > 0
334+
}
335+
var fooReturnValue: (any Codable)!
336+
var fooClosure: (() -> any Codable)?
337+
func foo() -> any Codable {
338+
fooCallsCount += 1
339+
if fooClosure != nil {
340+
return fooClosure!()
341+
} else {
342+
return fooReturnValue
343+
}
344+
}
345+
}
346+
"""
347+
)
348+
}
349+
322350
func testDeclarationVariable() throws {
323351
try assertProtocol(
324352
withDeclaration: """

0 commit comments

Comments
 (0)