forked from apollographql/apollo-ios
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEnumGenerator.swift
More file actions
112 lines (92 loc) · 3.4 KB
/
EnumGenerator.swift
File metadata and controls
112 lines (92 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import Foundation
import Stencil
public class EnumGenerator {
public struct SanitizedEnumValue {
// The raw value of the name
let name: String
/// The string declaring the name of the enum value
let nameVariableDeclaration: String
/// The string to use when using the enum value
let nameUsage: String
/// The description of the enum value
let description: String
/// If the enum value is deprecated.
let isDeprecated: Bool
init(astEnumValue: ASTEnumValue) {
self.name = astEnumValue.name
self.nameVariableDeclaration = astEnumValue.name.apollo.sanitizedVariableDeclaration
self.nameUsage = astEnumValue.name.apollo.sanitizedVariableUsage
self.description = astEnumValue.description
self.isDeprecated = astEnumValue.isDeprecated
}
}
/// Errors which can be encountered when generating an enum
public enum EnumGenerationError: Error, LocalizedError {
case kindIsNotAnEnum
case enumHasNilCases
public var errorDescription: String? {
switch self {
case .kindIsNotAnEnum:
return "An inappropriate `ASTTypeUsed.Kind` was passed into the enum generator."
case .enumHasNilCases:
return "An an enum typed was passed in but it had nil values. Check your schema for possible errors."
}
}
}
/// Designated initializer
public init() {
}
func run(typeUsed: ASTTypeUsed, options: ApolloCodegenOptions) throws -> String {
guard typeUsed.kind == .EnumType else {
throw EnumGenerationError.kindIsNotAnEnum
}
guard let enumValues = typeUsed.values else {
throw EnumGenerationError.enumHasNilCases
}
let cases: [ASTEnumValue]
if options.omitDeprecatedEnumCases {
cases = enumValues.filter { !$0.isDeprecated }
} else {
cases = enumValues
}
let context: [String: Any] = [
"modifier": options.modifier.prefixValue,
"enumType": typeUsed,
"cases": cases.map { SanitizedEnumValue(astEnumValue: $0) }
]
return try Environment().renderTemplate(string: self.enumTemplate, context: context)
}
/// A stencil template to use to render enums.
///
/// Variable to allow custom modifications, but MODIFY AT YOUR OWN RISK.
open var enumTemplate: String {
"""
{% if enumType.description != "" %}/// {{ enumType.description }}
{% endif %}{{ modifier }}enum {{ enumType.name }}: RawRepresentable, Codable, Equatable, Hashable, CaseIterable {
{{ modifier }}typealias RawValue = String
{% for case in cases %}{% if case.isDeprecated %}@available(*, deprecated, message: "Deprecated in schema")
{% endif %}{% if case.description != "" %}/// {{ case.description }}
{% endif %}case {{ case.nameVariableDeclaration }}
{% endfor %}/// An {{ enumType.name }} type not defined at the time this enum was generated
case __unknown(String)
{{ modifier }}var rawValue: String {
switch self {
{% for case in cases %}case .{{ case.nameUsage }}: return "{{ case.name }}"
{% endfor %}case .__unknown(let value): return value
}
}
{{ modifier }}init(rawValue: String) {
switch rawValue {
{% for case in cases %}case "{{ case.name }}": self = .{{ case.nameUsage }}
{% endfor %}default: self = .__unknown(rawValue)
}
}
{{ modifier }}static var allCases: [{{ enumType.name }}] {
[{% for case in cases %}
.{{ case.nameUsage }},{% endfor %}
]
}
}
"""
}
}