Skip to content

Commit

Permalink
Add access level for mock, variables and functions
Browse files Browse the repository at this point in the history
  • Loading branch information
0xLeif committed Nov 5, 2024
1 parent 3f9eba4 commit 52bd316
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 83 deletions.
79 changes: 42 additions & 37 deletions Sources/MockedMacros/MockedMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,32 @@ public struct MockedMacro: PeerMacro {
}
}

let mockClassName = "Mocked\(protocolDecl.name.text)"
let initAccessLevel = switch accessLevel {
case "public": "public"
case "open": "open"
case "package": "package"
default: "internal"
}

let mockClassName = "Mocked\(protocolDecl.name.text)"

let members = protocolDecl.memberBlock.members

// Variables

let variables: [Variable] = variableBuilder(members: members)

let variablesDefinitions: String = variableDefinitions(variables: variables, accessLevel: accessLevel)
let variablesInitDefinitions: String = variablesInitDefinitions(variables: variables)
let variablesInitAssignments: String = variablesInitAssignments(variables: variables)



// Functions

let functions: [Function] = functionBuilder(
protocolDecl: protocolDecl,
members: members
)

let functionVariableDefinitions: String = functionVariableDefinitions(functions: functions)
let functionVariableInitDefinitions: String = functionVariableInitDefinitions(functions: functions)
let functionVariableInitAssignments: String = functionVariableInitAssignments(functions: functions)
Expand All @@ -85,22 +91,22 @@ public struct MockedMacro: PeerMacro {
if let associatedTypeDecl = member.decl.as(AssociatedTypeDeclSyntax.self) {
let name = associatedTypeDecl.name.text
let constraint = associatedTypeDecl.inheritanceClause?.description.trimmingCharacters(in: .whitespacesAndNewlines)

if let constraint {
associatedTypes.append("\(name)\(constraint)")
} else {
associatedTypes.append(name)
}
}
}

// Construct generic type parameters if there are associated types
let genericValues = if associatedTypes.isEmpty {
""
} else {
"<" + associatedTypes.joined(separator: ", ") + ">"
}

return [
"""
/// Mocked version of \(raw: protocolDecl.name.text)
Expand All @@ -115,7 +121,7 @@ public struct MockedMacro: PeerMacro {
// MARK: - \(raw: mockClassName) init
init(
\(raw: initAccessLevel) init(
\(raw: variablesInitDefinitions)
\(raw: functionVariableInitDefinitions)
) {
Expand All @@ -131,15 +137,15 @@ public struct MockedMacro: PeerMacro {
"""
]
}

// MARK: - Variable helpers

private static func variableBuilder(members: MemberBlockItemListSyntax) -> [Variable] {
members.compactMap { member in
guard
let variable = member.decl.as(VariableDeclSyntax.self)
else { return nil }

guard let binding = variable.bindings.first else {
return nil
}
Expand All @@ -148,18 +154,18 @@ public struct MockedMacro: PeerMacro {
else {
fatalError("\(String(describing: binding.initializer?.syntaxNodeType))")
}

let name = binding.pattern
let type = typeAnnotation.description.trimmingCharacters(in: .whitespacesAndNewlines)

return Variable(
firstName: "\(name)",
secondName: nil,
type: type
)
}
}

private static func variableDefinitions(
variables: [Variable],
accessLevel: String
Expand All @@ -176,50 +182,50 @@ public struct MockedMacro: PeerMacro {
}
.joined(separator: "\n")
}

private static func variablesInitDefinitions(
variables: [Variable]
) -> String {
variables
.map { "\($0.declaration)," }
.joined(separator: "\n")
}

private static func variablesInitAssignments(
variables: [Variable]
) -> String {
variables
.map { "self.\($0.name) = \($0.name)" }
.joined(separator: "\n")
}

// MARK: - Function helpers

private static func functionBuilder(
protocolDecl: ProtocolDeclSyntax,
members: MemberBlockItemListSyntax
) -> [Function] {
let inheritsSendable = protocolDecl.inheritanceClause?.inheritedTypes.contains { inheritedType in
inheritedType.type.description.trimmingCharacters(in: .whitespacesAndNewlines) == "Sendable"
} ?? false

return members.compactMap { member in
guard
let function = member.decl.as(FunctionDeclSyntax.self)
else { return nil }

let name = function.name.text
var parameters: [Variable] = []
let returnType = function.signature.returnClause?.type ?? "Void"

let isAsync = function.signature.effectSpecifiers?.asyncSpecifier != nil
let canThrow = function.signature.effectSpecifiers?.throwsClause?.throwsSpecifier != nil

for parameter in function.signature.parameterClause.parameters {
let parameterFirstName = parameter.firstName.text
let parameterSecondName = parameter.secondName?.text
let parameterType = parameter.type.description.trimmingCharacters(in: .whitespacesAndNewlines)

parameters.append(
Variable(
firstName: parameterFirstName,
Expand All @@ -228,7 +234,7 @@ public struct MockedMacro: PeerMacro {
)
)
}

return Function(
name: "\(name)",
parameters: parameters,
Expand All @@ -239,31 +245,31 @@ public struct MockedMacro: PeerMacro {
)
}
}

private static func functionVariableDefinitions(
functions: [Function]
) -> String {
functions
.map { "private let \($0.overrideClosure)" }
.joined(separator: "\n")
}

private static func functionVariableInitDefinitions(
functions: [Function]
) -> String {
functions
.map { "\($0.closure) = nil" }
.joined(separator: ",\n")
}

private static func functionVariableInitAssignments(
functions: [Function]
) -> String {
functions
.map { "self.\($0.overrideName) = \($0.uniqueName)" }
.joined(separator: "\n")
}

private static func functionImplementations(
functions: [Function],
accessLevel: String
Expand All @@ -277,8 +283,8 @@ public struct MockedMacro: PeerMacro {
let parameterUsage: String = function.parameters
.map(\.usageName)
.joined(separator: ", ")


let effectSignature: String = if function.canThrow && function.isAsync {
"async throws "
} else if function.canThrow {
Expand All @@ -288,7 +294,7 @@ public struct MockedMacro: PeerMacro {
} else {
""
}

let callSignature: String = if function.canThrow && function.isAsync {
"try await "
} else if function.canThrow {
Expand All @@ -307,7 +313,6 @@ public struct MockedMacro: PeerMacro {
"internal"
}


if parameters.isEmpty {
return """
\(accessLevel) func \(function.name)() \(effectSignature)-> \(function.returnType ?? "Void") {
Expand All @@ -320,7 +325,7 @@ public struct MockedMacro: PeerMacro {
"""
} else {
return """
func \(function.name)(
\(accessLevel) func \(function.name)(
\(parameters)
) \(effectSignature)-> \(function.returnType ?? "Void") {
guard let \(function.overrideName) else {
Expand Down
Loading

0 comments on commit 52bd316

Please sign in to comment.