12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
+ import SwiftProtobuf
15
16
import SwiftProtobufPluginLibrary
16
17
17
- /// Base generator class that can be used to output a file from a Protobuf file descriptor.
18
+ private struct GeneratorError : Swift . Error {
19
+ let message : String
20
+ }
21
+
22
+ /// Base generator class that can be used to output files from Protobuf file descriptors.
23
+ ///
24
+ /// Subclasses must be annotated with `@main` to be properly invoked at runtime.
18
25
open class Generator {
19
- private var printer = CodePrinter ( indent : " " . unicodeScalars )
26
+ private var printer = SwiftProtobufPluginLibrary . CodePrinter ( )
20
27
21
- public let descriptor : FileDescriptor
22
- public let namer : SwiftProtobufNamer
23
- public let options : GeneratorOptions
28
+ /// Used for producing type names when generating code.
29
+ public private( set) var namer = SwiftProtobufPluginLibrary . SwiftProtobufNamer ( )
30
+ /// List of Swift module dependencies required by the current Protobuf file.
31
+ public private( set) var neededModules = [ String] ( )
32
+ /// Options to use when generating code.
33
+ public private( set) var options = GeneratorOptions . empty ( )
34
+ /// List of services specified in the current file.
35
+ public private( set) var services = [ SwiftProtobufPluginLibrary . ServiceDescriptor] ( )
24
36
25
- public var output : String {
26
- return self . printer. content
37
+ // MARK: - Overridable
38
+
39
+ /// File extension to use for generated file names.
40
+ open var outputFileExtension : String {
41
+ return " .connect.swift "
27
42
}
28
43
29
- public required init ( _ descriptor: FileDescriptor , options: GeneratorOptions ) {
30
- self . descriptor = descriptor
31
- self . options = options
32
- self . namer = SwiftProtobufNamer (
33
- currentFile: descriptor,
34
- protoFileToModuleMappings: options. protoToModuleMappings
35
- )
44
+ /// Initializer required by `SwiftProtobufPluginLibrary.CodeGenerator`.
45
+ public required init ( ) { }
46
+
47
+ /// Should be overridden by subclasses to write output for a given file descriptor.
48
+ /// Subclasses should call `super` before producing their own outputs.
49
+ /// May be called multiple times (once per file descriptor) over the lifetime of this class.
50
+ ///
51
+ /// - parameter descriptor: The file descriptor for which to generate code.
52
+ open func printContent( for descriptor: SwiftProtobufPluginLibrary . FileDescriptor ) {
53
+ self . printLine ( " // Code generated by protoc-gen-connect-swift. DO NOT EDIT. " )
54
+ self . printLine ( " // " )
55
+ self . printLine ( " // Source: \( descriptor. name) " )
56
+ self . printLine ( " // " )
57
+ self . printLine ( )
36
58
}
37
59
38
60
// MARK: - Output helpers
@@ -58,30 +80,75 @@ open class Generator {
58
80
self . printer. print ( " \n " )
59
81
}
60
82
61
- public func printCommentsIfNeeded( for entity: ProvidesSourceCodeLocation ) {
83
+ public func printCommentsIfNeeded(
84
+ for entity: SwiftProtobufPluginLibrary . ProvidesSourceCodeLocation
85
+ ) {
62
86
let comments = entity. protoSourceComments ( ) . trimmingCharacters ( in: . whitespacesAndNewlines)
63
87
if !comments. isEmpty {
64
88
self . printLine ( comments)
65
89
}
66
90
}
67
91
68
- public func printFilePreamble( ) {
69
- self . printLine ( " // Code generated by protoc-gen-connect-swift. DO NOT EDIT. " )
70
- self . printLine ( " // " )
71
- self . printLine ( " // Source: \( self . descriptor. name) " )
72
- self . printLine ( " // " )
73
- self . printLine ( )
74
- }
75
-
76
92
public func printModuleImports( adding additional: [ String ] = [ ] ) {
77
93
let defaults = [ " Connect " , " Foundation " , self . options. swiftProtobufModuleName]
78
94
let extraOptionImports = self . options. extraModuleImports
79
- let mappings = self . options. protoToModuleMappings
80
- . neededModules ( forFile: self . descriptor) ?? [ ]
81
- let allImports = ( defaults + mappings + extraOptionImports + additional) . sorted ( )
82
-
95
+ let allImports = ( defaults + self . neededModules + extraOptionImports + additional) . sorted ( )
83
96
for module in allImports {
84
97
self . printLine ( " import \( module) " )
85
98
}
86
99
}
87
100
}
101
+
102
+ extension Generator : SwiftProtobufPluginLibrary . CodeGenerator {
103
+ private func resetAndPrintFile(
104
+ for descriptor: SwiftProtobufPluginLibrary . FileDescriptor , with options: GeneratorOptions
105
+ ) -> String {
106
+ self . namer = SwiftProtobufPluginLibrary . SwiftProtobufNamer (
107
+ currentFile: descriptor,
108
+ protoFileToModuleMappings: self . options. protoToModuleMappings
109
+ )
110
+ self . neededModules = self . options. protoToModuleMappings
111
+ . neededModules ( forFile: descriptor) ?? [ ]
112
+ self . options = options
113
+ self . services = descriptor. services
114
+ self . printer = SwiftProtobufPluginLibrary . CodePrinter ( indent: " " . unicodeScalars)
115
+ self . printContent ( for: descriptor)
116
+ return self . printer. content
117
+ }
118
+
119
+ public func generate(
120
+ files: [ SwiftProtobufPluginLibrary . FileDescriptor ] ,
121
+ parameter: any SwiftProtobufPluginLibrary . CodeGeneratorParameter ,
122
+ protoCompilerContext _: any SwiftProtobufPluginLibrary . ProtoCompilerContext ,
123
+ generatorOutputs: any SwiftProtobufPluginLibrary . GeneratorOutputs
124
+ ) throws {
125
+ let options = try GeneratorOptions ( commandLineParameters: parameter)
126
+ guard options. generateAsyncMethods || options. generateCallbackMethods else {
127
+ throw GeneratorError (
128
+ message: " Either async methods or callback methods must be enabled "
129
+ )
130
+ }
131
+
132
+ for descriptor in files where !descriptor. services. isEmpty {
133
+ try generatorOutputs. add (
134
+ fileName: FilePathComponents ( path: descriptor. name) . outputFilePath (
135
+ withExtension: self . outputFileExtension, using: options. fileNaming
136
+ ) ,
137
+ contents: self . resetAndPrintFile ( for: descriptor, with: options)
138
+ )
139
+ }
140
+ }
141
+
142
+ public var supportedEditionRange : ClosedRange < SwiftProtobuf . Google_Protobuf_Edition > {
143
+ return SwiftProtobufPluginLibrary . DescriptorSet. bundledEditionsSupport
144
+ }
145
+
146
+ public var supportedFeatures : [
147
+ SwiftProtobufPluginLibrary . Google_Protobuf_Compiler_CodeGeneratorResponse . Feature
148
+ ] {
149
+ return [
150
+ . proto3Optional,
151
+ . supportsEditions,
152
+ ]
153
+ }
154
+ }
0 commit comments