Skip to content

Commit

Permalink
Generating properties and closures for enums
Browse files Browse the repository at this point in the history
  • Loading branch information
pietrocaselani committed Jul 2, 2019
1 parent 9e3f066 commit 92ac976
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 47 deletions.
31 changes: 31 additions & 0 deletions CouchTrackerCore/CodeGeneration/EnumClosures.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Given the following enum

```
enum ViewState<T>: EnumClosures {
case start(data: T)
case loading
case completed(count: Int, message: String)
}
```

will generate the following code

```
extension ViewState {
internal func onStart(_ fn: (T) -> Void) {
guard case let .start(data) = self else { return }
fn(data)
}
internal func onLoading(_ fn: () -> Void) {
guard case .loading = self else { return }
fn()
}
internal func onCompleted(_ fn: (Int, String) -> Void) {
guard case let .completed(count, message) = self else { return }
fn(count, message)
}
}
```
*/
public protocol EnumClosures {}
5 changes: 1 addition & 4 deletions CouchTrackerCore/CodeGeneration/EnumPoetry.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
public protocol EnumClosures {}

public protocol EnumProperties {}

// See `EnumClosures` and `EnumProperties`
public protocol EnumPoetry: EnumClosures, EnumProperties {}
40 changes: 40 additions & 0 deletions CouchTrackerCore/CodeGeneration/EnumProperties.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Given the following enum

```
enum ViewState<T>: EnumProperties {
case start(T)
case loading
case completed(Int, String)
}
```

will generate the following code

```
extension ViewState {
internal var isStart: Bool {
guard case .start = self else { return false }
return true
}
internal var isLoading: Bool {
guard case .loading = self else { return false }
return true
}
internal var isCompleted: Bool {
guard case .completed = self else { return false }
return true
}

internal var start: T? {
guard case let .start(data) = self else { return nil }
return (data)
}
internal var completed: (count: Int, message: String)? {
guard case let .completed(count, message) = self else { return nil }
return (count, message)
}
}
```
*/
public protocol EnumProperties {}
7 changes: 0 additions & 7 deletions CouchTrackerCore/Movies/Manager/MoviesManagerViewState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,3 @@ public enum MoviesManagerViewState: Hashable, EnumPoetry {
case loading
case showing(pages: [ModulePage], selectedIndex: Int)
}

extension MoviesManagerViewState {
var showing: (pages: [ModulePage], selectedIndex: Int)? {
guard case let .showing(pages, x) = self else { return nil }
return (pages: pages, selectedIndex: x)
}
}
2 changes: 0 additions & 2 deletions SourceryTemplates/EnumClosures.stencil
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{% macro associatedValueNamedType associatedValue %}{% if associatedValue.localName %}{{ associatedValue.localName }}{% else %}value{{ forloop.counter }}{% endif %}{% endmacro %}

{% macro associatedValueTypes associatedValues %}{% for associatedValue in associatedValues %}{% if forloop.first %}{{ associatedValue.typeName }}{% else %}, {{ associatedValue.typeName }}{% endif %}{% endfor %}{% endmacro %}
{% macro associatedValueNames associatedValues %}{% for associatedValue in case.associatedValues %}{% if forloop.first %}{% call associatedValueNamedType associatedValue %}{% else %}, {% call associatedValueNamedType associatedValue %}{% endif %}{% endfor %}{% endmacro %}

// MARK: - EnumClosures

{% for enum in types.enums where enum.implements.EnumClosures %}
Expand Down
6 changes: 2 additions & 4 deletions SourceryTemplates/EnumProperties.stencil
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{% macro associatedValueNamedType associatedValue %}{% if associatedValue.localName %}{{ associatedValue.localName }}{% else %}value{{ forloop.counter }}{% endif %}{% endmacro %}

{% macro associatedValueTypes associatedValues %}{% for associatedValue in associatedValues %}{% if forloop.first %}{{ associatedValue.typeName }}{% else %}, {{ associatedValue.typeName }}{% endif %}{% endfor %}{% endmacro %}
{% macro associatedValueNames associatedValues %}{% for associatedValue in case.associatedValues %}{% if forloop.first %}{% call associatedValueNamedType associatedValue %}{% else %}, {% call associatedValueNamedType associatedValue %}{% endif %}{% endfor %}{% endmacro %}

{% macro associatedTypeAsTuple associatedValues %}{% if associatedValues.count == 1 %}{{ associatedValues[0].typeName }}{% else %}({% for associatedValue in associatedValues %}{% if forloop.first %}{% call associatedValueNamedType associatedValue %}: {{ associatedValue.typeName }}{% else %}, {% call associatedValueNamedType associatedValue %}: {{ associatedValue.typeName }}{% endif %}{% endfor %}){% endif %}{% endmacro %}
// MARK: - EnumProperties

{% for enum in types.enums where enum.implements.EnumProperties %}
Expand All @@ -13,10 +12,9 @@ extension {{ enum.name }} {
return true
}
{% endfor %}

{% for case in enum.cases %}
{% if case.hasAssociatedValue %}
{{ enum.accessLevel }} var {{ case.name }}: ({% call associatedValueTypes case.associatedValues %})? {
{{ enum.accessLevel }} var {{ case.name }}: {% call associatedTypeAsTuple case.associatedValues %}? {
guard case let .{{ case.name }}({% call associatedValueNames case.associatedValues %}) = self else { return nil }
return ({% call associatedValueNames case.associatedValues %})
}
Expand Down
30 changes: 0 additions & 30 deletions SourceryTemplates/EnumTypes.stencil

This file was deleted.

0 comments on commit 92ac976

Please sign in to comment.