Skip to content

Commit

Permalink
Added support for generating lazy vars for computed properties
Browse files Browse the repository at this point in the history
  • Loading branch information
adammcarter committed Mar 23, 2024
1 parent 59fe066 commit 2da1320
Show file tree
Hide file tree
Showing 3 changed files with 249 additions and 116 deletions.
30 changes: 14 additions & 16 deletions Sources/ProtocolWitnessingClient/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,23 +160,22 @@ import ProtocolWitnessing
//Thread.sleep(forTimeInterval: 10)





struct MyClient {
var isThing: Bool {
get { true }
set { print(newValue) }
}
lazy var getSomething: Bool = {
true
}()

struct ProtocolWitness {
var _isThing: Bool = {
var _getSomething: Bool = {
true
}()

var isThing: Bool {
var getSomething: Bool {
get {
_isThing
}
set {
print(newValue)
_getSomething
}
}

Expand All @@ -202,14 +201,13 @@ struct MyClient {



var prod = MyClient.ProtocolWitness.production()

prod.getSomething


//var prod = MyClient.ProtocolWitness.production()
//
//print(prod.isThing)
//
//var mock = prod
//mock._isThing = false
var mock = prod
mock._getSomething = false

//
//print(mock.isThing)
188 changes: 120 additions & 68 deletions Sources/ProtocolWitnessingMacros/ProtocolWitnessingMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,70 +69,7 @@ public struct WitnessingMacro: MemberMacro {








let expandedInitParameters = combinedInitParameters
.map {
let staticOrEmpty = $0.isStatic ? "static " : ""

return "\(staticOrEmpty)var _\($0.name)\($0.rhs)"
}
.joined(separator: "\n")




let computedProperties = makeComputedPropertyDetails(from: structDecl)

let expandedComputedProperties = computedProperties
.map {
let asyncThrows = if $0.isAsync, $0.isThrowing {
" async throws"
} else if $0.isAsync {
" async"
} else if $0.isThrowing {
" throws"
} else {
""
}

let getExpression = if $0.isAsync, $0.isThrowing {
"try await _\($0.name)()"
} else if $0.isThrowing {
"try _\($0.name)()"
} else {
"_\($0.name)"
}

let staticOrEmpty = $0.isStatic ? "static " : ""
let lhs = "\(staticOrEmpty)\($0.letOrVar) \($0.name)"
let rhs = "\($0.type)"
let getName = "get\(asyncThrows)"
let get = "\(getName) { \(getExpression) }"
let set = $0.setter.flatMap { "\n\($0)" } ?? ""

return """
\(lhs): \(rhs) {
\(get)\(set)
}
"""
}
.joined(separator: "\n\n")



let expandedPropertiesSeparator =
expandedInitParameters.isEmpty || expandedComputedProperties.isEmpty ? "" : "\n\n"

let expandedProperties = [
expandedInitParameters,
expandedComputedProperties
]
.joined(separator: expandedPropertiesSeparator)




Expand Down Expand Up @@ -314,7 +251,86 @@ public struct WitnessingMacro: MemberMacro {



let productionValues = """







let witnessProperties = combinedInitParameters
.map {
let staticOrEmpty = $0.isStatic ? "static " : ""

return "\(staticOrEmpty)var _\($0.name)\($0.rhs)"
}
.joined(separator: "\n")




let computedProperties = makeComputedPropertyDetails(from: structDecl)

let expandedComputedProperties = computedProperties
.map {
let asyncThrows = if $0.isAsync, $0.isThrowing {
" async throws"
} else if $0.isAsync {
" async"
} else if $0.isThrowing {
" throws"
} else {
""
}

let getExpression = if $0.isAsync, $0.isThrowing {
"try await _\($0.name)()"
} else if $0.isThrowing {
"try _\($0.name)()"
} else {
"_\($0.name)"
}

let staticOrEmpty = $0.isStatic ? "static " : ""
let lhs = "\(staticOrEmpty)\($0.letOrVar) \($0.name)"
let rhs = "\($0.type)"
let getName = "get\(asyncThrows)"
let get = "\(getName) { \(getExpression) }"
let set = $0.setter.flatMap { "\n\($0)" } ?? ""

return """
\(lhs): \(rhs) {
\(get)\(set)
}
"""
}
.joined(separator: "\n\n")



let expandedPropertiesSeparator =
witnessProperties.isEmpty || expandedComputedProperties.isEmpty ? "" : "\n\n"

let expandedProperties = [
witnessProperties,
expandedComputedProperties
]
.joined(separator: expandedPropertiesSeparator)














let productionType = """
private static var _\(productionName): \(typeName)?
\(productionFunctionDeclaration)
Expand All @@ -341,7 +357,7 @@ public struct WitnessingMacro: MemberMacro {
struct \(raw: witnessTypeName) {
\(raw: expandedInit)
\(raw: productionValues)
\(raw: productionType)
}
"""
} else {
Expand All @@ -353,7 +369,7 @@ public struct WitnessingMacro: MemberMacro {
\(raw: expandedFunctions)
\(raw: productionValues)
\(raw: productionType)
}
"""
}
Expand Down Expand Up @@ -450,6 +466,27 @@ public struct WitnessingMacro: MemberMacro {
isThrowing: isThrowing,
isStatic: isStatic
)
} else if
binding
.initializer?
.value
.as(FunctionCallExprSyntax.self)?
.calledExpression
.as(ClosureExprSyntax.self)?
.statements
.trimmedDescription
!= nil
{
return ComputedPropertyDetails(
letOrVar: "var",
name: binding.pattern.trimmedDescription,
type: type,
accessor: "_\(bindingSpecifier.text)",
setter: nil,
isAsync: false,
isThrowing: false,
isStatic: isStatic
)
} else if binding.initializer == nil {
return ComputedPropertyDetails(
letOrVar: "var",
Expand Down Expand Up @@ -510,7 +547,22 @@ public struct WitnessingMacro: MemberMacro {
.statements
.trimmedDescription

let closureContents = getterClosureContents ?? accessors?.trimmedDescription
let functionCallContents = member
.decl
.as(VariableDeclSyntax.self)?
.bindings
.first?
.initializer?
.value
.as(FunctionCallExprSyntax.self)?
.calledExpression
.as(ClosureExprSyntax.self)?
.statements
.trimmedDescription

let closureContents = functionCallContents
?? getterClosureContents
?? accessors?.trimmedDescription

return varDecl
.bindings
Expand All @@ -519,7 +571,7 @@ public struct WitnessingMacro: MemberMacro {

if
includesComputed == false,
accessorBlock != nil
accessorBlock != nil || closureContents != nil
{
return nil
}
Expand Down
Loading

0 comments on commit 2da1320

Please sign in to comment.