Skip to content

Commit 26030ee

Browse files
committed
Allow module names to be configured
Modifications: - Give the protobuf generator its own config struct - Use it in the protoc-gen-grpc-swift options - Add new options for module names and propagate them through to the config - Use the custom module names where applicable Result: - Generated code can include different module name imports.
1 parent 64f97e9 commit 26030ee

File tree

10 files changed

+148
-86
lines changed

10 files changed

+148
-86
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ let products: [Product] = [
3535
let dependencies: [Package.Dependency] = [
3636
.package(
3737
url: "https://github.com/grpc/grpc-swift.git",
38-
from: "2.0.0"
38+
branch: "main"
3939
),
4040
.package(
4141
url: "https://github.com/apple/swift-protobuf.git",

Sources/GRPCProtobufCodeGen/ProtobufCodeGenParser.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,18 @@ package struct ProtobufCodeGenParser {
3636
let extraModuleImports: [String]
3737
let protoToModuleMappings: ProtoFileToModuleMappings
3838
let accessLevel: CodeGenerator.Config.AccessLevel
39+
let moduleNames: ProtobufCodeGenerator.Config.ModuleNames
3940

4041
package init(
4142
protoFileModuleMappings: ProtoFileToModuleMappings,
4243
extraModuleImports: [String],
43-
accessLevel: CodeGenerator.Config.AccessLevel
44+
accessLevel: CodeGenerator.Config.AccessLevel,
45+
moduleNames: ProtobufCodeGenerator.Config.ModuleNames
4446
) {
4547
self.extraModuleImports = extraModuleImports
4648
self.protoToModuleMappings = protoFileModuleMappings
4749
self.accessLevel = accessLevel
50+
self.moduleNames = moduleNames
4851
}
4952

5053
package func parse(descriptor: FileDescriptor) throws -> CodeGenerationRequest {
@@ -86,10 +89,10 @@ package struct ProtobufCodeGenParser {
8689
dependencies: self.codeDependencies(file: descriptor),
8790
services: services,
8891
makeSerializerCodeSnippet: { messageType in
89-
"GRPCProtobuf.ProtobufSerializer<\(messageType)>()"
92+
"\(self.moduleNames.grpcProtobuf).ProtobufSerializer<\(messageType)>()"
9093
},
9194
makeDeserializerCodeSnippet: { messageType in
92-
"GRPCProtobuf.ProtobufDeserializer<\(messageType)>()"
95+
"\(self.moduleNames.grpcProtobuf).ProtobufDeserializer<\(messageType)>()"
9396
}
9497
)
9598
}
@@ -102,7 +105,7 @@ extension ProtobufCodeGenParser {
102105
}
103106

104107
var codeDependencies: [Dependency] = [
105-
Dependency(module: "GRPCProtobuf", accessLevel: .internal)
108+
Dependency(module: self.moduleNames.grpcProtobuf, accessLevel: .internal)
106109
]
107110
// If there's a dependency on a bundled proto then add the SwiftProtobuf import.
108111
//
@@ -113,7 +116,11 @@ extension ProtobufCodeGenParser {
113116
}
114117

115118
if dependsOnBundledProto {
116-
codeDependencies.append(Dependency(module: "SwiftProtobuf", accessLevel: self.accessLevel))
119+
let dependency = Dependency(
120+
module: self.moduleNames.swiftProtobuf,
121+
accessLevel: self.accessLevel
122+
)
123+
codeDependencies.append(dependency)
117124
}
118125

119126
// Adding as dependencies the modules containing generated code or types for

Sources/GRPCProtobufCodeGen/ProtobufCodeGenerator.swift

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ package import GRPCCodeGen
1818
package import SwiftProtobufPluginLibrary
1919

2020
package struct ProtobufCodeGenerator {
21-
internal var config: GRPCCodeGen.CodeGenerator.Config
21+
internal var config: ProtobufCodeGenerator.Config
2222

2323
package init(
24-
config: GRPCCodeGen.CodeGenerator.Config
24+
config: ProtobufCodeGenerator.Config
2525
) {
2626
self.config = config
2727
}
@@ -34,12 +34,58 @@ package struct ProtobufCodeGenerator {
3434
let parser = ProtobufCodeGenParser(
3535
protoFileModuleMappings: protoFileModuleMappings,
3636
extraModuleImports: extraModuleImports,
37-
accessLevel: self.config.accessLevel
37+
accessLevel: self.config.accessLevel,
38+
moduleNames: self.config.moduleNames
3839
)
39-
let codeGenerator = GRPCCodeGen.CodeGenerator(config: self.config)
40+
41+
var codeGeneratorConfig = GRPCCodeGen.CodeGenerator.Config(
42+
accessLevel: self.config.accessLevel,
43+
accessLevelOnImports: self.config.accessLevelOnImports,
44+
client: self.config.generateClient,
45+
server: self.config.generateServer,
46+
indentation: self.config.indentation
47+
)
48+
codeGeneratorConfig.grpcCoreModuleName = self.config.moduleNames.grpcCore
49+
let codeGenerator = GRPCCodeGen.CodeGenerator(config: codeGeneratorConfig)
4050

4151
let codeGenerationRequest = try parser.parse(descriptor: fileDescriptor)
4252
let sourceFile = try codeGenerator.generate(codeGenerationRequest)
4353
return sourceFile.contents
4454
}
4555
}
56+
57+
extension ProtobufCodeGenerator {
58+
package struct Config {
59+
package var accessLevel: GRPCCodeGen.CodeGenerator.Config.AccessLevel
60+
package var accessLevelOnImports: Bool
61+
62+
package var generateClient: Bool
63+
package var generateServer: Bool
64+
65+
package var indentation: Int
66+
package var moduleNames: ModuleNames
67+
68+
package struct ModuleNames {
69+
package var grpcCore: String
70+
package var grpcProtobuf: String
71+
package var swiftProtobuf: String
72+
73+
package static let defaults = Self(
74+
grpcCore: "GRPCCore",
75+
grpcProtobuf: "GRPCProtobuf",
76+
swiftProtobuf: "SwiftProtobuf"
77+
)
78+
}
79+
80+
package static var defaults: Self {
81+
Self(
82+
accessLevel: .internal,
83+
accessLevelOnImports: false,
84+
generateClient: true,
85+
generateServer: true,
86+
indentation: 4,
87+
moduleNames: .defaults
88+
)
89+
}
90+
}
91+
}

Sources/protoc-gen-grpc-swift/GenerateGRPC.swift

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ final class GenerateGRPC: SwiftProtobufPluginLibrary.CodeGenerator {
9696
fileNamingOption: options.fileNaming
9797
)
9898

99-
let config = CodeGenerator.Config(options: options)
100-
let fileGenerator = ProtobufCodeGenerator(config: config)
99+
let fileGenerator = ProtobufCodeGenerator(config: options.config)
101100
let contents = try fileGenerator.generateCode(
102101
fileDescriptor: descriptor,
103102
protoFileModuleMappings: options.protoToModuleMappings,
@@ -181,24 +180,3 @@ private func splitPath(pathname: String) -> (dir: String, base: String, suffix:
181180
}
182181
return (dir: dir, base: base, suffix: suffix)
183182
}
184-
185-
extension GRPCCodeGen.CodeGenerator.Config {
186-
init(options: GeneratorOptions) {
187-
let accessLevel: GRPCCodeGen.CodeGenerator.Config.AccessLevel
188-
switch options.visibility {
189-
case .internal:
190-
accessLevel = .internal
191-
case .package:
192-
accessLevel = .package
193-
case .public:
194-
accessLevel = .public
195-
}
196-
197-
self.init(
198-
accessLevel: accessLevel,
199-
accessLevelOnImports: options.useAccessLevelOnImports,
200-
client: options.generateClient,
201-
server: options.generateServer
202-
)
203-
}
204-
}

Sources/protoc-gen-grpc-swift/Options.swift

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
import GRPCCodeGen
18+
import GRPCProtobufCodeGen
1719
import SwiftProtobufPluginLibrary
1820

1921
enum GenerationError: Error, CustomStringConvertible {
@@ -43,35 +45,13 @@ enum FileNaming: String {
4345
}
4446

4547
struct GeneratorOptions {
46-
enum Visibility: String {
47-
case `internal` = "Internal"
48-
case `public` = "Public"
49-
case `package` = "Package"
50-
51-
var sourceSnippet: String {
52-
switch self {
53-
case .internal:
54-
return "internal"
55-
case .public:
56-
return "public"
57-
case .package:
58-
return "package"
59-
}
60-
}
61-
}
62-
63-
private(set) var visibility = Visibility.internal
64-
65-
private(set) var generateServer = true
66-
private(set) var generateClient = true
67-
6848
private(set) var protoToModuleMappings = ProtoFileToModuleMappings()
6949
private(set) var fileNaming = FileNaming.fullPath
7050
private(set) var extraModuleImports: [String] = []
71-
private(set) var gRPCModuleName = "GRPC"
72-
private(set) var swiftProtobufModuleName = "SwiftProtobuf"
51+
7352
private(set) var generateReflectionData = false
74-
private(set) var useAccessLevelOnImports = false
53+
54+
private(set) var config: ProtobufCodeGenerator.Config = .defaults
7555

7656
init(parameter: any CodeGeneratorParameter) throws {
7757
try self.init(pairs: parameter.parsedPairs)
@@ -81,22 +61,22 @@ struct GeneratorOptions {
8161
for pair in pairs {
8262
switch pair.key {
8363
case "Visibility":
84-
if let value = Visibility(rawValue: pair.value) {
85-
self.visibility = value
64+
if let value = GRPCCodeGen.CodeGenerator.Config.AccessLevel(protocOption: pair.value) {
65+
self.config.accessLevel = value
8666
} else {
8767
throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
8868
}
8969

9070
case "Server":
9171
if let value = Bool(pair.value.lowercased()) {
92-
self.generateServer = value
72+
self.config.generateServer = value
9373
} else {
9474
throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
9575
}
9676

9777
case "Client":
9878
if let value = Bool(pair.value.lowercased()) {
99-
self.generateClient = value
79+
self.config.generateClient = value
10080
} else {
10181
throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
10282
}
@@ -129,14 +109,21 @@ struct GeneratorOptions {
129109

130110
case "GRPCModuleName":
131111
if !pair.value.isEmpty {
132-
self.gRPCModuleName = pair.value
112+
self.config.moduleNames.grpcCore = pair.value
113+
} else {
114+
throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
115+
}
116+
117+
case "GRPCProtobufModuleName":
118+
if !pair.value.isEmpty {
119+
self.config.moduleNames.grpcProtobuf = pair.value
133120
} else {
134121
throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
135122
}
136123

137124
case "SwiftProtobufModuleName":
138125
if !pair.value.isEmpty {
139-
self.swiftProtobufModuleName = pair.value
126+
self.config.moduleNames.swiftProtobuf = pair.value
140127
} else {
141128
throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
142129
}
@@ -150,7 +137,7 @@ struct GeneratorOptions {
150137

151138
case "UseAccessLevelOnImports":
152139
if let value = Bool(pair.value.lowercased()) {
153-
self.useAccessLevelOnImports = value
140+
self.config.accessLevelOnImports = value
154141
} else {
155142
throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
156143
}
@@ -194,3 +181,18 @@ extension String.SubSequence {
194181
return String(trimmed)
195182
}
196183
}
184+
185+
extension GRPCCodeGen.CodeGenerator.Config.AccessLevel {
186+
fileprivate init?(protocOption value: String) {
187+
switch value {
188+
case "Internal":
189+
self = .internal
190+
case "Public":
191+
self = .public
192+
case "Package":
193+
self = .package
194+
default:
195+
return nil
196+
}
197+
}
198+
}
5.95 KB
Binary file not shown.

Tests/GRPCProtobufCodeGenTests/ProtobufCodeGeneratorTests.swift

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,10 @@ struct ProtobufCodeGeneratorTests {
2727

2828
@Test("Generate", arguments: [CodeGenerator.Config.AccessLevel.internal])
2929
func generate(accessLevel: GRPCCodeGen.CodeGenerator.Config.AccessLevel) throws {
30-
let generator = ProtobufCodeGenerator(
31-
config: CodeGenerator.Config(
32-
accessLevel: accessLevel,
33-
accessLevelOnImports: false,
34-
client: true,
35-
server: true,
36-
indentation: 2
37-
)
38-
)
30+
var config = ProtobufCodeGenerator.Config.defaults
31+
config.accessLevel = accessLevel
32+
config.indentation = 2
33+
let generator = ProtobufCodeGenerator(config: config)
3934

4035
let access: String
4136
switch accessLevel {
@@ -1062,6 +1057,35 @@ struct ProtobufCodeGeneratorTests {
10621057

10631058
#expect(generated == expected)
10641059
}
1060+
1061+
@Test("Generate with different module names")
1062+
func generateWithDifferentModuleNames() throws {
1063+
var config = ProtobufCodeGenerator.Config.defaults
1064+
let defaultNames = config.moduleNames
1065+
1066+
config.accessLevel = .public
1067+
config.indentation = 2
1068+
config.moduleNames.grpcCore = String(config.moduleNames.grpcCore.reversed())
1069+
config.moduleNames.grpcProtobuf = String(config.moduleNames.grpcProtobuf.reversed())
1070+
config.moduleNames.swiftProtobuf = String(config.moduleNames.swiftProtobuf.reversed())
1071+
1072+
let generator = ProtobufCodeGenerator(config: config)
1073+
let generated = try generator.generateCode(
1074+
fileDescriptor: Self.fileDescriptor,
1075+
protoFileModuleMappings: ProtoFileToModuleMappings(),
1076+
extraModuleImports: []
1077+
)
1078+
1079+
// Mustn't contain the default names.
1080+
#expect(!generated.contains(defaultNames.grpcCore))
1081+
#expect(!generated.contains(defaultNames.grpcProtobuf))
1082+
#expect(!generated.contains(defaultNames.swiftProtobuf))
1083+
1084+
// Must contain the configured names.
1085+
#expect(generated.contains(config.moduleNames.grpcCore))
1086+
#expect(generated.contains(config.moduleNames.grpcProtobuf))
1087+
#expect(generated.contains(config.moduleNames.swiftProtobuf))
1088+
}
10651089
}
10661090

10671091
@Suite("File-without-services (foo-messages.proto)")
@@ -1071,15 +1095,11 @@ struct ProtobufCodeGeneratorTests {
10711095

10721096
@Test("Generate")
10731097
func generate() throws {
1074-
let generator = ProtobufCodeGenerator(
1075-
config: CodeGenerator.Config(
1076-
accessLevel: .public,
1077-
accessLevelOnImports: false,
1078-
client: true,
1079-
server: true,
1080-
indentation: 2
1081-
)
1082-
)
1098+
var config: ProtobufCodeGenerator.Config = .defaults
1099+
config.accessLevel = .public
1100+
config.indentation = 2
1101+
1102+
let generator = ProtobufCodeGenerator(config: config)
10831103

10841104
let generated = try generator.generateCode(
10851105
fileDescriptor: Self.fileDescriptor,

Tests/GRPCProtobufCodeGenTests/Utilities.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ func parseDescriptor(
7676
let parser = ProtobufCodeGenParser(
7777
protoFileModuleMappings: .init(),
7878
extraModuleImports: extraModuleImports,
79-
accessLevel: accessLevel
79+
accessLevel: accessLevel,
80+
moduleNames: .defaults
8081
)
8182
return try parser.parse(descriptor: descriptor)
8283
}

dev/protos/generate.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ function generate_test_service_descriptor_set {
105105
proto_path="$(dirname "$proto")"
106106
output="$root/Tests/GRPCProtobufCodeGenTests/Generated/test-service.pb"
107107

108-
invoke_protoc --descriptor_set_out="$output" "$proto" -I "$proto_path" --include_source_info
108+
invoke_protoc --descriptor_set_out="$output" "$proto" -I "$proto_path" \
109+
--include_imports \
110+
--include_source_info
109111
}
110112

111113
function generate_foo_service_descriptor_set {

0 commit comments

Comments
 (0)