-
-
Notifications
You must be signed in to change notification settings - Fork 508
/
TuistConfig.swift
183 lines (151 loc) · 5.7 KB
/
TuistConfig.swift
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import Basic
import Foundation
import TuistCore
/// This model allows to configure Tuist.
public class TuistConfig: Equatable, Hashable {
/// Contains options related to the project generation.
///
/// - generateManifestElement: When passed, Tuist generates the projects, targets and schemes to compile the project manifest.
public enum GenerationOption: Hashable {
case generateManifest
case xcodeProjectName(TemplateString)
}
/// Generation options.
public let generationOptions: [GenerationOption]
/// Returns the default Tuist configuration.
public static var `default`: TuistConfig {
return TuistConfig(generationOptions: [.generateManifest])
}
/// Initializes the tuist cofiguration.
///
/// - Parameters:
/// - generationOptions: Generation options.
public init(generationOptions: [GenerationOption]) {
self.generationOptions = generationOptions
}
static func at(_ path: AbsolutePath, cache: GraphLoaderCaching, modelLoader: GeneratorModelLoading, fileHandler _: FileHandling) throws -> TuistConfig {
if let tuistConfig = cache.tuistConfig(path) {
return tuistConfig
} else {
let tuistConfig = try modelLoader.loadTuistConfig(at: path)
cache.add(tuistConfig: tuistConfig, path: path)
return tuistConfig
}
}
// MARK: - Hashable
public func hash(into hasher: inout Hasher) {
hasher.combine(generationOptions)
}
// MARK: - Equatable
public static func == (lhs: TuistConfig, rhs: TuistConfig) -> Bool {
return lhs.generationOptions == rhs.generationOptions
}
}
public struct TemplateString: Encodable, Decodable, Hashable {
public let rawString: String
public init(rawString: String) {
self.rawString = rawString
}
}
extension TemplateString: ExpressibleByStringLiteral {
public init(stringLiteral: String) {
rawString = stringLiteral
}
}
extension TemplateString: CustomStringConvertible {
public var description: String {
return rawString
}
}
extension TemplateString: ExpressibleByStringInterpolation {
public init(stringInterpolation: StringInterpolation) {
rawString = stringInterpolation.string
}
public struct StringInterpolation: StringInterpolationProtocol {
var string: String
public init(literalCapacity _: Int, interpolationCount _: Int) {
string = String()
}
public mutating func appendLiteral(_ literal: String) {
string.append(literal)
}
public func appendInterpolation(_: String) {}
}
}
extension TemplateString {
public enum Token: String {
case projectName = "${project_name}"
}
}
extension TemplateString.StringInterpolation {
public mutating func appendInterpolation(_ token: TemplateString.Token) {
string.append(token.rawValue)
}
}
extension TemplateString.Token {
enum CodingKeys: String, CodingKey {
case projectName
}
internal init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let enumCase = try container.decode(String.self)
switch enumCase {
case CodingKeys.projectName.rawValue: self = .projectName
default: throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Unknown enum case '\(enumCase)'"))
}
}
internal func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .projectName: try container.encode(CodingKeys.projectName.rawValue)
}
}
}
extension TuistConfig.GenerationOption {
enum CodingKeys: String, CodingKey {
case generateManifest
case xcodeProjectName
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if container.allKeys.contains(.generateManifest), try container.decodeNil(forKey: .generateManifest) == false {
self = .generateManifest
return
}
if container.allKeys.contains(.xcodeProjectName), try container.decodeNil(forKey: .xcodeProjectName) == false {
var associatedValues = try container.nestedUnkeyedContainer(forKey: .xcodeProjectName)
let associatedValue0 = try associatedValues.decode(TemplateString.self)
self = .xcodeProjectName(associatedValue0)
return
}
throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Unknown enum case"))
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .generateManifest:
_ = container.nestedContainer(keyedBy: CodingKeys.self, forKey: .generateManifest)
case let .xcodeProjectName(associatedValue0):
var associatedValues = container.nestedUnkeyedContainer(forKey: .xcodeProjectName)
try associatedValues.encode(associatedValue0)
}
}
}
extension TemplateString.Token: Equatable {}
public func == (lhs: TemplateString.Token, rhs: TemplateString.Token) -> Bool {
switch (lhs, rhs) {
case (.projectName, .projectName):
return true
}
}
// MARK: - TuistConfig.GenerationOption AutoEquatable
extension TuistConfig.GenerationOption: Equatable {}
public func == (lhs: TuistConfig.GenerationOption, rhs: TuistConfig.GenerationOption) -> Bool {
switch (lhs, rhs) {
case (.generateManifest, .generateManifest):
return true
case let (.xcodeProjectName(lhs), .xcodeProjectName(rhs)):
return lhs == rhs
default: return false
}
}