@@ -18,110 +18,184 @@ import Foundation
18
18
19
19
let configFileName = " grpc-swift-proto-generator-config.json "
20
20
21
- /// The configuration of the build plugin.
21
+ /// The config of the build plugin.
22
22
struct BuildPluginConfig : Codable {
23
- /// The visibility of the generated files.
24
- ///
25
- /// Defaults to `Internal`.
26
- var visibility : GenerationConfig . Visibility
27
- /// Whether server code is generated.
28
- ///
29
- /// Defaults to `true`.
30
- var server : Bool
31
- /// Whether client code is generated.
32
- ///
33
- /// Defaults to `true`.
34
- var client : Bool
35
- /// Whether message code is generated.
36
- ///
37
- /// Defaults to `true`.
38
- var message : Bool
39
- /// Whether imports should have explicit access levels.
40
- ///
41
- /// Defaults to `false`.
42
- var useAccessLevelOnImports : Bool
43
-
44
- /// Specify the directory in which to search for imports.
45
- ///
46
- /// Paths are relative to the location of the specifying config file.
47
- /// Build plugins only have access to files within the target's source directory.
48
- /// May be specified multiple times; directories will be searched in order.
49
- /// The target source directory is always appended
50
- /// to the import paths.
51
- var importPaths : [ String ]
52
-
53
- /// The path to the `protoc` binary.
54
- ///
55
- /// If this is not set, Swift Package Manager will try to find the tool itself.
56
- var protocPath : String ?
23
+ /// Config defining which components should be considered when generating source.
24
+ struct Generate {
25
+ /// Whether server code is generated.
26
+ ///
27
+ /// Defaults to `true`.
28
+ var servers : Bool
29
+ /// Whether client code is generated.
30
+ ///
31
+ /// Defaults to `true`.
32
+ var clients : Bool
33
+ /// Whether message code is generated.
34
+ ///
35
+ /// Defaults to `true`.
36
+ var messages : Bool
37
+
38
+ static let defaults = Self (
39
+ servers: true ,
40
+ clients: true ,
41
+ messages: true
42
+ )
43
+
44
+ private init ( servers: Bool , clients: Bool , messages: Bool ) {
45
+ self . servers = servers
46
+ self . clients = clients
47
+ self . messages = messages
48
+ }
49
+ }
50
+
51
+ /// Config relating to the generated code itself.
52
+ struct GeneratedSource {
53
+ /// The visibility of the generated files.
54
+ ///
55
+ /// Defaults to `Internal`.
56
+ var accessLevel : GenerationConfig . AccessLevel
57
+ /// Whether imports should have explicit access levels.
58
+ ///
59
+ /// Defaults to `false`.
60
+ var useAccessLevelOnImports : Bool
61
+
62
+ static let defaults = Self (
63
+ accessLevel: . internal,
64
+ useAccessLevelOnImports: false
65
+ )
66
+
67
+ private init ( accessLevel: GenerationConfig . AccessLevel , useAccessLevelOnImports: Bool ) {
68
+ self . accessLevel = accessLevel
69
+ self . useAccessLevelOnImports = useAccessLevelOnImports
70
+ }
71
+ }
72
+
73
+ /// Config relating to the protoc invocation.
74
+ struct Protoc {
75
+ /// Specify the directory in which to search for imports.
76
+ ///
77
+ /// Paths are relative to the location of the specifying config file.
78
+ /// Build plugins only have access to files within the target's source directory.
79
+ /// May be specified multiple times; directories will be searched in order.
80
+ /// The target source directory is always appended
81
+ /// to the import paths.
82
+ var importPaths : [ String ]
83
+
84
+ /// The path to the `protoc` executable binary.
85
+ ///
86
+ /// If this is not set, Swift Package Manager will try to find the tool itself.
87
+ var executablePath : String ?
88
+
89
+ static let defaults = Self (
90
+ importPaths: [ ] ,
91
+ executablePath: nil
92
+ )
93
+
94
+ private init ( importPaths: [ String ] , executablePath: String ? ) {
95
+ self . importPaths = importPaths
96
+ self . executablePath = executablePath
97
+ }
98
+ }
99
+
100
+ /// Config defining which components should be considered when generating source.
101
+ var generate : Generate
102
+ /// Config relating to the nature of the generated code.
103
+ var generatedSource : GeneratedSource
104
+ /// Config relating to the protoc invocation.
105
+ var protoc : Protoc
106
+
107
+ static let defaults = Self (
108
+ generate: Generate . defaults,
109
+ generatedSource: GeneratedSource . defaults,
110
+ protoc: Protoc . defaults
111
+ )
112
+ private init ( generate: Generate , generatedSource: GeneratedSource , protoc: Protoc ) {
113
+ self . generate = generate
114
+ self . generatedSource = generatedSource
115
+ self . protoc = protoc
116
+ }
57
117
58
118
// Codable conformance with defaults
59
119
enum CodingKeys : String , CodingKey {
60
- case visibility
61
- case server
62
- case client
63
- case message
120
+ case generate
121
+ case generatedSource
122
+ case protoc
123
+ }
124
+
125
+
126
+ init ( from decoder: any Decoder ) throws {
127
+ let container = try decoder. container ( keyedBy: CodingKeys . self)
128
+
129
+ self . generate = try container. decodeIfPresent ( Generate . self, forKey: . generate) ?? Self . defaults. generate
130
+ self . generatedSource = try container. decodeIfPresent ( GeneratedSource . self, forKey: . generatedSource) ?? Self . defaults. generatedSource
131
+ self . protoc = try container. decodeIfPresent ( Protoc . self, forKey: . protoc) ?? Self . defaults. protoc
132
+ }
133
+ }
134
+
135
+ extension BuildPluginConfig . Generate : Codable {
136
+ // Codable conformance with defaults
137
+ enum CodingKeys : String , CodingKey {
138
+ case servers
139
+ case clients
140
+ case messages
141
+ }
142
+
143
+ init ( from decoder: any Decoder ) throws {
144
+ let container = try decoder. container ( keyedBy: CodingKeys . self)
145
+
146
+ self . servers = try container. decodeIfPresent ( Bool . self, forKey: . servers) ?? Self . defaults. servers
147
+ self . clients = try container. decodeIfPresent ( Bool . self, forKey: . clients) ?? Self . defaults. clients
148
+ self . messages = try container. decodeIfPresent ( Bool . self, forKey: . messages) ?? Self . defaults. messages
149
+ }
150
+ }
151
+
152
+ extension BuildPluginConfig . GeneratedSource : Codable {
153
+ // Codable conformance with defaults
154
+ enum CodingKeys : String , CodingKey {
155
+ case accessLevel
64
156
case useAccessLevelOnImports
65
- case importPaths
66
- case protocPath
67
157
}
68
158
69
- let defaultVisibility : GenerationConfig . Visibility = . internal
70
- let defaultServer = true
71
- let defaultClient = true
72
- let defaultMessage = true
73
- let defaultUseAccessLevelOnImports = false
74
- let defaultImportPaths : [ String ] = [ ]
159
+ init ( from decoder: any Decoder ) throws {
160
+ let container = try decoder. container ( keyedBy: CodingKeys . self)
161
+
162
+ self . accessLevel = try container. decodeIfPresent ( GenerationConfig . AccessLevel. self, forKey: . accessLevel)
163
+ ?? Self . defaults. accessLevel
164
+ self . useAccessLevelOnImports = try container. decodeIfPresent ( Bool . self, forKey: . useAccessLevelOnImports)
165
+ ?? Self . defaults. useAccessLevelOnImports
166
+ }
167
+ }
168
+
169
+ extension BuildPluginConfig . Protoc : Codable {
170
+ // Codable conformance with defaults
171
+ enum CodingKeys : String , CodingKey {
172
+ case importPaths
173
+ case executablePath
174
+ }
75
175
76
176
init ( from decoder: any Decoder ) throws {
77
177
let container = try decoder. container ( keyedBy: CodingKeys . self)
78
178
79
- self . visibility =
80
- try container. decodeIfPresent ( GenerationConfig . Visibility. self, forKey: . visibility)
81
- ?? defaultVisibility
82
- self . server = try container. decodeIfPresent ( Bool . self, forKey: . server) ?? defaultServer
83
- self . client = try container. decodeIfPresent ( Bool . self, forKey: . client) ?? defaultClient
84
- self . message = try container. decodeIfPresent ( Bool . self, forKey: . message) ?? defaultMessage
85
- self . useAccessLevelOnImports =
86
- try container. decodeIfPresent ( Bool . self, forKey: . useAccessLevelOnImports)
87
- ?? defaultUseAccessLevelOnImports
88
- self . importPaths =
89
- try container. decodeIfPresent ( [ String ] . self, forKey: . importPaths) ?? defaultImportPaths
90
- self . protocPath = try container. decodeIfPresent ( String . self, forKey: . protocPath)
179
+ self . importPaths = try container. decodeIfPresent ( [ String ] . self, forKey: . importPaths)
180
+ ?? Self . defaults. importPaths
181
+ self . executablePath = try container. decodeIfPresent ( String . self, forKey: . executablePath)
91
182
}
92
183
}
93
184
94
185
extension GenerationConfig {
95
- init ( configurationFile: BuildPluginConfig , configurationFilePath: URL , outputPath: URL ) {
96
- self . visibility = configurationFile. visibility
97
- self . server = configurationFile. server
98
- self . client = configurationFile. client
99
- self . message = configurationFile. message
186
+ init ( buildPluginConfig: BuildPluginConfig , configFilePath: URL , outputPath: URL ) {
187
+ self . server = buildPluginConfig. generate. servers
188
+ self . client = buildPluginConfig. generate. clients
189
+ self . message = buildPluginConfig. generate. messages
100
190
// hard-code full-path to avoid collisions since this goes into a temporary directory anyway
101
191
self . fileNaming = . fullPath
102
- self . useAccessLevelOnImports = configurationFile. useAccessLevelOnImports
103
- self . importPaths = [ ]
104
-
192
+ self . visibility = buildPluginConfig. generatedSource. accessLevel
193
+ self . useAccessLevelOnImports = buildPluginConfig. generatedSource. useAccessLevelOnImports
105
194
// Generate absolute paths for the imports relative to the config file in which they are specified
106
- self . importPaths = configurationFile. importPaths. map { relativePath in
107
- configurationFilePath. deletingLastPathComponent ( ) . relativePath + " / " + relativePath
108
- }
109
- self . protocPath = configurationFile. protocPath
110
- self . outputPath = outputPath. relativePath
111
- }
112
- }
113
-
114
- extension GenerationConfig . Visibility : Codable {
115
- init ? ( rawValue: String ) {
116
- switch rawValue. lowercased ( ) {
117
- case " internal " :
118
- self = . internal
119
- case " public " :
120
- self = . public
121
- case " package " :
122
- self = . package
123
- default :
124
- return nil
195
+ self . importPaths = buildPluginConfig. protoc. importPaths. map { relativePath in
196
+ configFilePath. deletingLastPathComponent ( ) . absoluteStringNoScheme + " / " + relativePath
125
197
}
198
+ self . protocPath = buildPluginConfig. protoc. executablePath
199
+ self . outputPath = outputPath. absoluteStringNoScheme
126
200
}
127
201
}
0 commit comments