Last active
June 20, 2020 11:38
-
-
Save AliSoftware/691eee22464b6f9e1796a85111a9c2ee to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum Demo { | |
case simple | |
case oneValue(Int) | |
case twoValues(String, Double) | |
case threeValues(one: Int, two: Float, [Int]) | |
} | |
//: # Direct exposition in the enum | |
//: ## Sourcery Template | |
/* enum-values.stencil | |
{% for enum in types.enums %} | |
{{ enum.accessLevel }} extension {{enum.localName}} { | |
{% for case in enum.cases %} | |
{% if case.hasAssociatedValue %} | |
{% set returnType %}{% filter removeNewlines:leading %} | |
{% if case.associatedValues.count == 1 %} | |
{{case.associatedValues.first.typeName}} | |
{% else %} | |
({% for av in case.associatedValues %} | |
{% if av.localName %}{{av.localName}}: {% endif %}{{av.typeName}}{% if not forloop.last %}, {% endif %} | |
{% endfor %}) | |
{% endif %} | |
{% endfilter %}{% endset %} | |
var {{case.name}}: {{returnType}}? { | |
guard case let .{{case.name}}(value) = self else { return nil } | |
return value | |
} | |
{% else %} | |
var {{case.name}}: Void? { | |
guard case .{{case.name}} = self else { return nil } | |
return () | |
} | |
{% endif %} | |
var is{{case.name|upperFirstLetter}}: Bool { | |
return {{case.name}} != nil | |
} | |
{% endfor %} | |
} | |
{% endfor %} | |
*/ | |
//: ## Sourcery Generated code | |
internal extension Demo { | |
var simple: Void? { | |
guard case .simple = self else { return nil } | |
return () | |
} | |
var isSimple: Bool { | |
return simple != nil | |
} | |
var oneValue: Int? { | |
guard case let .oneValue(value) = self else { return nil } | |
return value | |
} | |
var isOneValue: Bool { | |
return oneValue != nil | |
} | |
var twoValues: (String,Double)? { | |
guard case let .twoValues(value) = self else { return nil } | |
return value | |
} | |
var isTwoValues: Bool { | |
return twoValues != nil | |
} | |
var threeValues: (one:Int,two:Float,[Int])? { | |
guard case let .threeValues(value) = self else { return nil } | |
return value | |
} | |
var isThreeValues: Bool { | |
return threeValues != nil | |
} | |
} | |
//: ## Demo 1 | |
let d1 = Demo.simple | |
let d2 = Demo.oneValue(42) | |
let d3 = Demo.twoValues("Hello", 13.37) | |
let d4 = Demo.threeValues(one: 42, two: 13.37, [1,2,3]) | |
let allExamples = ["d1": d1, "d2": d2, "d3": d3, "d4": d4] | |
for (name, sut) in allExamples { | |
print("== \(name) ==") | |
print(" - simple: \(sut.isSimple) = \(String(describing: sut.simple))") | |
print(" - oneValue: \(sut.isOneValue) = \(String(describing: sut.oneValue))") | |
print(" - twoValues: \(sut.isTwoValues) = \(String(describing: sut.twoValues))") | |
print(" - threeValues: \(sut.isThreeValues) = \(String(describing: sut.threeValues))") | |
} | |
d4.threeValues!.one // 42 | |
d4.threeValues!.two // 13.37 | |
d4.threeValues!.2 // [1, 2, 3] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum Demo { | |
case simple | |
case oneValue(Int) | |
case twoValues(String, Double) | |
case threeValues(one: Int, two: Float, [Int]) | |
} | |
//: # Indirect exposition via `is` and `as` properties | |
//: ## Sourcery Template | |
/* enum-values-2.stencil | |
{% macro returnType case %}{% filter removeNewlines:leading %} | |
{% if case.associatedValues.count == 1 %} | |
{{case.associatedValues.first.typeName}} | |
{% else %} | |
({% for av in case.associatedValues %} | |
{% if av.localName %}{{av.localName}}: {% endif %}{{av.typeName}}{% if not forloop.last %}, {% endif %} | |
{% endfor %}) | |
{% endif %} | |
{% endfilter %}{% endmacro %} | |
{% for enum in types.enums %} | |
{{ enum.accessLevel }} extension {{enum.localName}} { | |
struct EnumAssociatedValues { | |
fileprivate base: {{enum.localName}} | |
{% for case in enum.cases %}{% if case.hasAssociatedValue %} | |
var {{case.name}}: {% call returnType case %}? { | |
guard case let .{{case.name}}(value) = base else { return nil } | |
return value | |
} | |
{% else %} | |
var {{case.name}}: Void? { | |
guard case .{{case.name}} = base else { return nil } | |
return () | |
} | |
{% endif %}{% endfor %} | |
} | |
var `as`: EnumAssociatedValues { .init(base: self) } | |
struct EnumIdentity { | |
fileprivate base: {{enum.localName}}.EnumAssociatedValue | |
{% for case in enum.cases %} | |
var {{case.name}}: Bool { | |
return base.{{case.name}} != nil | |
} | |
{% endfor %} | |
} | |
var `is`: EnumIdentity { .init(base: as) } | |
} | |
{% endfor %} | |
*/ | |
//: ## Sourcery Generated Code | |
internal extension Demo { | |
struct EnumAssociatedValues { | |
fileprivate let base: Demo | |
var simple: Void? { | |
guard case .simple = base else { return nil } | |
return () | |
} | |
var oneValue: Int? { | |
guard case let .oneValue(value) = base else { return nil } | |
return value | |
} | |
var twoValues: (String,Double)? { | |
guard case let .twoValues(value) = base else { return nil } | |
return value | |
} | |
var threeValues: (one:Int,two:Float,[Int])? { | |
guard case let .threeValues(value) = base else { return nil } | |
return value | |
} | |
} | |
var `as`: EnumAssociatedValues { .init(base: self) } | |
struct EnumIdentity { | |
fileprivate let base: Demo.EnumAssociatedValues | |
var simple: Bool { | |
return base.simple != nil | |
} | |
var oneValue: Bool { | |
return base.oneValue != nil | |
} | |
var twoValues: Bool { | |
return base.twoValues != nil | |
} | |
var threeValues: Bool { | |
return base.threeValues != nil | |
} | |
} | |
var `is`: EnumIdentity { .init(base: `as`) } | |
} | |
//: ## Demo 2 | |
let d1 = Demo.simple | |
let d2 = Demo.oneValue(42) | |
let d3 = Demo.twoValues("Hello", 13.37) | |
let d4 = Demo.threeValues(one: 42, two: 13.37, [1,2,3]) | |
let allExamples = ["d1": d1, "d2": d2, "d3": d3, "d4": d4] | |
for (name, sut) in allExamples { | |
print("== \(name) ==") | |
print(" - simple: \(sut.is.simple) = \(String(describing: sut.as.simple))") | |
print(" - oneValue: \(sut.is.oneValue) = \(String(describing: sut.as.oneValue))") | |
print(" - twoValues: \(sut.is.twoValues) = \(String(describing: sut.as.twoValues))") | |
print(" - threeValues: \(sut.is.threeValues) = \(String(describing: sut.as.threeValues))") | |
} | |
d4.threeValues!.one // 42 | |
d4.threeValues!.two // 13.37 | |
d4.threeValues!.2 // [1, 2, 3] |
Simplified version of the demo without the implementation details getting in the way:
enum Demo {
case simple
case oneValue(Int)
case twoValues(String, Double)
case threeValues(one: Int, two: Float, [Int])
}
let d1 = Demo.simple
let d2 = Demo.oneValue(42)
let d3 = Demo.twoValues("Hello", 13.37)
let d4 = Demo.threeValues(one: 42, two: 13.37, [1,2,3])
d1.is.simple // true
d1.is.oneValue // false
d2.is.oneValue // true
d2.as.oneValue // Optional(42)
d3.as.oneValue // nil
d4.as.threeValues!.one // 42
d4.as.threeValues!.two // 13.37
d4.as.threeValues!.2 // [1, 2, 3]
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Console output: