@@ -18,110 +18,184 @@ import Foundation
1818
1919let configFileName = " grpc-swift-proto-generator-config.json "
2020
21- /// The configuration of the build plugin.
21+ /// The config of the build plugin.
2222struct 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+ }
57117
58118 // Codable conformance with defaults
59119 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
64156 case useAccessLevelOnImports
65- case importPaths
66- case protocPath
67157 }
68158
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+ }
75175
76176 init ( from decoder: any Decoder ) throws {
77177 let container = try decoder. container ( keyedBy: CodingKeys . self)
78178
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)
91182 }
92183}
93184
94185extension 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
100190 // hard-code full-path to avoid collisions since this goes into a temporary directory anyway
101191 self . fileNaming = . fullPath
102- self . useAccessLevelOnImports = configurationFile. useAccessLevelOnImports
103- self . importPaths = [ ]
104-
192+ self . visibility = buildPluginConfig. generatedSource. accessLevel
193+ self . useAccessLevelOnImports = buildPluginConfig. generatedSource. useAccessLevelOnImports
105194 // 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
125197 }
198+ self . protocPath = buildPluginConfig. protoc. executablePath
199+ self . outputPath = outputPath. absoluteStringNoScheme
126200 }
127201}
0 commit comments