Skip to content

Commit

Permalink
Merge pull request #76 from /issues/2
Browse files Browse the repository at this point in the history
Add handling inout parameter
  • Loading branch information
Matejkob authored Dec 30, 2023
2 parents 0326d01 + be4b509 commit bb042da
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 13 deletions.
39 changes: 27 additions & 12 deletions Sources/SpyableMacro/Factories/ClosureFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import SwiftSyntaxBuilder
///
/// The following code:
/// ```swift
/// var fooClosure: ((String, Int) async throws -> Data)?
/// var fooClosure: ((inout String, Int) async throws -> Data)?
///
/// try await fooClosure!(text, count)
/// try await fooClosure!(&text, count)
/// ```
/// would be generated for a function like this:
/// ```swift
/// func foo(text: String, count: Int) async throws -> Data
/// func foo(text: inout String, count: Int) async throws -> Data
/// ```
/// and an argument `variablePrefix` equal to `foo`.
///
Expand Down Expand Up @@ -81,18 +81,22 @@ struct ClosureFactory {
)
}

let arguments = LabeledExprListSyntax {
for parameter in functionSignature.parameterClause.parameters {
let baseName = parameter.secondName ?? parameter.firstName

if parameter.isInoutParameter {
LabeledExprSyntax(expression: InOutExprSyntax(expression: DeclReferenceExprSyntax(baseName: baseName)))
} else {
LabeledExprSyntax(expression: DeclReferenceExprSyntax(baseName: baseName))
}
}
}

var expression: ExprSyntaxProtocol = FunctionCallExprSyntax(
calledExpression: calledExpression,
leftParen: .leftParenToken(),
arguments: LabeledExprListSyntax {
for parameter in functionSignature.parameterClause.parameters {
LabeledExprSyntax(
expression: DeclReferenceExprSyntax(
baseName: parameter.secondName ?? parameter.firstName
)
)
}
},
arguments: arguments,
rightParen: .rightParenToken()
)

Expand All @@ -111,3 +115,14 @@ struct ClosureFactory {
TokenSyntax.identifier(variablePrefix + "Closure")
}
}

private extension FunctionParameterListSyntax.Element {
var isInoutParameter: Bool {
if let attributedType = self.type.as(AttributedTypeSyntax.self),
attributedType.specifier?.text == TokenSyntax.keyword(.inout).text {
return true
} else {
return false
}
}
}
18 changes: 17 additions & 1 deletion Tests/SpyableMacroTests/Factories/UT_ClosureFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ final class UT_ClosureFactory: XCTestCase {
)
}

func testVariableDeclarationWithInoutAttribute() throws {
try assertProtocolFunction(
withFunctionDeclaration: "func _ignore_(value: inout String)",
prefixForVariable: "_prefix_",
expectingVariableDeclaration: "var _prefix_Closure: ((inout String) -> Void)?"
)
}

func testVariableDeclarationEverything() throws {
try assertProtocolFunction(
withFunctionDeclaration: """
Expand Down Expand Up @@ -115,13 +123,21 @@ final class UT_ClosureFactory: XCTestCase {
)
}

func testCallExpressionWithInoutAttribute() throws {
try assertProtocolFunction(
withFunctionDeclaration: "func _ignore_(value: inout String)",
prefixForVariable: "_prefix_",
expectingCallExpression: "_prefix_Closure?(&value)"
)
}

func testCallExpressionEverything() throws {
try assertProtocolFunction(
withFunctionDeclaration: """
func _ignore_(text: inout String, product: (UInt?, name: String), added: (() -> Void)?, removed: @escaping () -> Bool) async throws -> String?
""",
prefixForVariable: "_prefix_",
expectingCallExpression: "try await _prefix_Closure!(text, product, added, removed)"
expectingCallExpression: "try await _prefix_Closure!(&text, product, added, removed)"
)
}

Expand Down

0 comments on commit bb042da

Please sign in to comment.