Skip to content

Commit 12a7366

Browse files
authored
Use nested protocols (#2132)
Motivation: The minimum Swift version we require supports protocols being declared within another type. This means that all protocols and types we generate for a service can be declared within the enum namespace for that service and we can remove the typealiases. Modifications: - Declare generated protocols within their enum namespace - Inline generated service descriptors Result: Simpler generated code
1 parent d70fbad commit 12a7366

10 files changed

+218
-576
lines changed

Sources/GRPCCodeGen/Internal/StructuredSwift+ServiceMetadata.swift

Lines changed: 40 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ extension TypealiasDescription {
4343
extension VariableDescription {
4444
/// ```
4545
/// static let descriptor = GRPCCore.MethodDescriptor(
46-
/// service: <serviceNamespace>.descriptor.fullyQualifiedService,
46+
/// service: GRPCCore.ServiceDescriptor(fullyQualifiedServiceName: "<literalFullyQualifiedService>"),
4747
/// method: "<literalMethodName>"
4848
/// ```
4949
package static func methodDescriptor(
5050
accessModifier: AccessModifier? = nil,
51-
serviceNamespace: String,
51+
literalFullyQualifiedService: String,
5252
literalMethodName: String
5353
) -> Self {
5454
return VariableDescription(
@@ -62,9 +62,11 @@ extension VariableDescription {
6262
arguments: [
6363
FunctionArgumentDescription(
6464
label: "service",
65-
expression: .identifierType(
66-
.member([serviceNamespace, "descriptor"])
67-
).dot("fullyQualifiedService")
65+
expression: .functionCall(
66+
.serviceDescriptor(
67+
literalFullyQualifiedService: literalFullyQualifiedService
68+
)
69+
)
6870
),
6971
FunctionArgumentDescription(
7072
label: "method",
@@ -77,18 +79,34 @@ extension VariableDescription {
7779
}
7880

7981
/// ```
80-
/// static let descriptor = GRPCCore.ServiceDescriptor.<namespacedProperty>
82+
/// static let descriptor = GRPCCore.ServiceDescriptor(fullyQualifiedService: <LiteralFullyQualifiedService>)
8183
/// ```
8284
package static func serviceDescriptor(
8385
accessModifier: AccessModifier? = nil,
84-
namespacedProperty: String
86+
literalFullyQualifiedService name: String
8587
) -> Self {
8688
return VariableDescription(
8789
accessModifier: accessModifier,
8890
isStatic: true,
8991
kind: .let,
9092
left: .identifierPattern("descriptor"),
91-
right: .identifier(.type(.serviceDescriptor)).dot(namespacedProperty)
93+
right: .functionCall(.serviceDescriptor(literalFullyQualifiedService: name))
94+
)
95+
}
96+
}
97+
98+
extension FunctionCallDescription {
99+
package static func serviceDescriptor(
100+
literalFullyQualifiedService: String
101+
) -> Self {
102+
FunctionCallDescription(
103+
calledExpression: .identifier(.type(.serviceDescriptor)),
104+
arguments: [
105+
FunctionArgumentDescription(
106+
label: "fullyQualifiedService",
107+
expression: .literal(literalFullyQualifiedService)
108+
)
109+
]
92110
)
93111
}
94112
}
@@ -97,16 +115,14 @@ extension ExtensionDescription {
97115
/// ```
98116
/// extension GRPCCore.ServiceDescriptor {
99117
/// static let <PropertyName> = Self(
100-
/// package: "<LiteralNamespaceName>",
101-
/// service: "<LiteralServiceName>"
118+
/// fullyQualifiedService: <LiteralFullyQualifiedService>
102119
/// )
103120
/// }
104121
/// ```
105122
package static func serviceDescriptor(
106123
accessModifier: AccessModifier? = nil,
107124
propertyName: String,
108-
literalNamespace: String,
109-
literalService: String
125+
literalFullyQualifiedService: String
110126
) -> ExtensionDescription {
111127
return ExtensionDescription(
112128
onType: "GRPCCore.ServiceDescriptor",
@@ -117,17 +133,7 @@ extension ExtensionDescription {
117133
kind: .let,
118134
left: .identifier(.pattern(propertyName)),
119135
right: .functionCall(
120-
calledExpression: .identifierType(.member("Self")),
121-
arguments: [
122-
FunctionArgumentDescription(
123-
label: "package",
124-
expression: .literal(literalNamespace)
125-
),
126-
FunctionArgumentDescription(
127-
label: "service",
128-
expression: .literal(literalService)
129-
),
130-
]
136+
.serviceDescriptor(literalFullyQualifiedService: literalFullyQualifiedService)
131137
)
132138
)
133139
]
@@ -169,7 +175,7 @@ extension EnumDescription {
169175
accessModifier: AccessModifier? = nil,
170176
name: String,
171177
literalMethod: String,
172-
serviceNamespace: String,
178+
literalFullyQualifiedService: String,
173179
inputType: String,
174180
outputType: String
175181
) -> Self {
@@ -182,7 +188,7 @@ extension EnumDescription {
182188
.variable(
183189
.methodDescriptor(
184190
accessModifier: accessModifier,
185-
serviceNamespace: serviceNamespace,
191+
literalFullyQualifiedService: literalFullyQualifiedService,
186192
literalMethodName: literalMethod
187193
)
188194
),
@@ -209,7 +215,7 @@ extension EnumDescription {
209215
/// ```
210216
package static func methodsNamespace(
211217
accessModifier: AccessModifier? = nil,
212-
serviceNamespace: String,
218+
literalFullyQualifiedService: String,
213219
methods: [MethodDescriptor]
214220
) -> EnumDescription {
215221
var description = EnumDescription(accessModifier: accessModifier, name: "Method")
@@ -221,7 +227,7 @@ extension EnumDescription {
221227
accessModifier: accessModifier,
222228
name: method.name.base,
223229
literalMethod: method.name.base,
224-
serviceNamespace: serviceNamespace,
230+
literalFullyQualifiedService: literalFullyQualifiedService,
225231
inputType: method.inputType,
226232
outputType: method.outputType
227233
)
@@ -245,57 +251,31 @@ extension EnumDescription {
245251
/// enum Method {
246252
/// ...
247253
/// }
248-
/// @available(...)
249-
/// typealias StreamingServiceProtocol = ...
250-
/// @available(...)
251-
/// typealias ServiceProtocol = ...
252-
/// ...
253254
/// }
254255
/// ```
255256
package static func serviceNamespace(
256257
accessModifier: AccessModifier? = nil,
257258
name: String,
258-
serviceDescriptorProperty: String,
259-
client: Bool,
260-
server: Bool,
259+
literalFullyQualifiedService: String,
261260
methods: [MethodDescriptor]
262261
) -> EnumDescription {
263262
var description = EnumDescription(accessModifier: accessModifier, name: name)
264263

265-
// static let descriptor = GRPCCore.ServiceDescriptor.<namespacedServicePropertyName>
264+
// static let descriptor = GRPCCore.ServiceDescriptor(fullyQualifiedService: "...")
266265
let descriptor = VariableDescription.serviceDescriptor(
267266
accessModifier: accessModifier,
268-
namespacedProperty: serviceDescriptorProperty
267+
literalFullyQualifiedService: literalFullyQualifiedService
269268
)
270269
description.members.append(.variable(descriptor))
271270

272271
// enum Method { ... }
273272
let methodsNamespace: EnumDescription = .methodsNamespace(
274273
accessModifier: accessModifier,
275-
serviceNamespace: name,
274+
literalFullyQualifiedService: literalFullyQualifiedService,
276275
methods: methods
277276
)
278277
description.members.append(.enum(methodsNamespace))
279278

280-
// Typealiases for the various protocols.
281-
var typealiasNames: [String] = []
282-
if server {
283-
typealiasNames.append("StreamingServiceProtocol")
284-
typealiasNames.append("ServiceProtocol")
285-
}
286-
if client {
287-
typealiasNames.append("ClientProtocol")
288-
typealiasNames.append("Client")
289-
}
290-
let typealiases: [Declaration] = typealiasNames.map { alias in
291-
.typealias(
292-
accessModifier: accessModifier,
293-
name: alias,
294-
existingType: .member(name + "_" + alias)
295-
)
296-
}
297-
description.members.append(contentsOf: typealiases)
298-
299279
return description
300280
}
301281
}
@@ -312,27 +292,22 @@ extension [CodeBlock] {
312292
/// ```
313293
package static func serviceMetadata(
314294
accessModifier: AccessModifier? = nil,
315-
service: ServiceDescriptor,
316-
client: Bool,
317-
server: Bool
295+
service: ServiceDescriptor
318296
) -> Self {
319297
var blocks: [CodeBlock] = []
320298

321299
let serviceNamespace: EnumDescription = .serviceNamespace(
322300
accessModifier: accessModifier,
323301
name: service.namespacedGeneratedName,
324-
serviceDescriptorProperty: service.namespacedServicePropertyName,
325-
client: client,
326-
server: server,
302+
literalFullyQualifiedService: service.fullyQualifiedName,
327303
methods: service.methods
328304
)
329305
blocks.append(CodeBlock(item: .declaration(.enum(serviceNamespace))))
330306

331307
let descriptorExtension: ExtensionDescription = .serviceDescriptor(
332308
accessModifier: accessModifier,
333309
propertyName: service.namespacedServicePropertyName,
334-
literalNamespace: service.namespace.base,
335-
literalService: service.name.base
310+
literalFullyQualifiedService: service.fullyQualifiedName
336311
)
337312
blocks.append(CodeBlock(item: .declaration(.extension(descriptorExtension))))
338313

Sources/GRPCCodeGen/Internal/Translator/ClientCodeTranslator.swift

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -86,25 +86,41 @@ struct ClientCodeTranslator {
8686
) -> [CodeBlock] {
8787
var blocks = [CodeBlock]()
8888

89-
let protocolName = "\(service.namespacedGeneratedName)_ClientProtocol"
90-
let protocolTypealias = "\(service.namespacedGeneratedName).ClientProtocol"
91-
let structName = "\(service.namespacedGeneratedName)_Client"
89+
let `extension` = ExtensionDescription(
90+
onType: service.namespacedGeneratedName,
91+
declarations: [
92+
// protocol ClientProtocol { ... }
93+
.commentable(
94+
.preFormatted(service.documentation),
95+
.protocol(
96+
.clientProtocol(
97+
accessLevel: accessModifier,
98+
name: "ClientProtocol",
99+
methods: service.methods
100+
)
101+
)
102+
),
92103

93-
let clientProtocol: ProtocolDescription = .clientProtocol(
94-
accessLevel: accessModifier,
95-
name: protocolName,
96-
methods: service.methods
97-
)
98-
blocks.append(
99-
CodeBlock(
100-
comment: .preFormatted(service.documentation),
101-
item: .declaration(.protocol(clientProtocol))
102-
)
104+
// struct Client: ClientProtocol { ... }
105+
.commentable(
106+
.preFormatted(service.documentation),
107+
.struct(
108+
.client(
109+
accessLevel: accessModifier,
110+
name: "Client",
111+
serviceEnum: service.namespacedGeneratedName,
112+
clientProtocol: "ClientProtocol",
113+
methods: service.methods
114+
)
115+
)
116+
),
117+
]
103118
)
119+
blocks.append(.declaration(.extension(`extension`)))
104120

105121
let extensionWithDefaults: ExtensionDescription = .clientMethodSignatureWithDefaults(
106122
accessLevel: accessModifier,
107-
name: protocolTypealias,
123+
name: "\(service.namespacedGeneratedName).ClientProtocol",
108124
methods: service.methods,
109125
serializer: serializer,
110126
deserializer: deserializer
@@ -115,27 +131,13 @@ struct ClientCodeTranslator {
115131

116132
let extensionWithExplodedAPI: ExtensionDescription = .explodedClientMethods(
117133
accessLevel: accessModifier,
118-
on: protocolTypealias,
134+
on: "\(service.namespacedGeneratedName).ClientProtocol",
119135
methods: service.methods
120136
)
121137
blocks.append(
122138
CodeBlock(item: .declaration(.extension(extensionWithExplodedAPI)))
123139
)
124140

125-
let clientStruct: StructDescription = .client(
126-
accessLevel: accessModifier,
127-
name: structName,
128-
serviceEnum: service.namespacedGeneratedName,
129-
clientProtocol: protocolTypealias,
130-
methods: service.methods
131-
)
132-
blocks.append(
133-
CodeBlock(
134-
comment: .preFormatted(service.documentation),
135-
item: .declaration(.struct(clientStruct))
136-
)
137-
)
138-
139141
return blocks
140142
}
141143
}

Sources/GRPCCodeGen/Internal/Translator/IDLToStructuredSwiftTranslator.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ struct IDLToStructuredSwiftTranslator: Translator {
4040

4141
let metadata = metadataTranslator.translate(
4242
accessModifier: accessModifier,
43-
service: service,
44-
client: client,
45-
server: server
43+
service: service
4644
)
4745
codeBlocks.append(contentsOf: metadata)
4846

Sources/GRPCCodeGen/Internal/Translator/MetadataTranslator.swift

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,8 @@ struct MetadataTranslator {
1919

2020
func translate(
2121
accessModifier: AccessModifier,
22-
service: ServiceDescriptor,
23-
client: Bool,
24-
server: Bool
22+
service: ServiceDescriptor
2523
) -> [CodeBlock] {
26-
.serviceMetadata(
27-
accessModifier: accessModifier,
28-
service: service,
29-
client: client,
30-
server: server
31-
)
24+
.serviceMetadata(accessModifier: accessModifier, service: service)
3225
}
3326
}

0 commit comments

Comments
 (0)