Skip to content

Commit 53855b1

Browse files
[CodeGenLib] Translator for Client Code (#1748)
Motivation: In the generated client code for a service described in a Source IDL file we want to have: - a protocol declaring the methods for a client, with the serializer and deserializer as parameters. - an extension for the protocol defining the methods of the client, without the serializer and deserializer as parameters, that are calling the already declared methods, providing the default Protobuf serializer and deserializer. - a struct representing the generated client that has a GRPCClient as a property and conforms to the Client Protocol. Modifications: - Implemented the ClientCodeTranslator struct that contains all the methods for creating the `StructuredSwiftRepresentation` for the client code. - Added a new struct in the `StructuredSwiftRepresentation` that represents closure signatures, and a new `ParameterDescription` property that is set only when the parameter is a closure signature. - Added and modified render functions for the `StructuredSwiftRepresentation` additions. - Implemented snippet tests. Result: Client code can now be generated for a CodeGenerationRequest object.
1 parent ced0d70 commit 53855b1

File tree

6 files changed

+1251
-32
lines changed

6 files changed

+1251
-32
lines changed

Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift

Lines changed: 174 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,11 @@ struct TextBasedRenderer: RendererProtocol {
202202
}
203203

204204
/// Renders the specified identifier.
205-
func renderedIdentifier(_ identifier: IdentifierDescription) -> String {
205+
func renderIdentifier(_ identifier: IdentifierDescription) {
206206
switch identifier {
207-
case .pattern(let string): return string
207+
case .pattern(let string): writer.writeLine(string)
208208
case .type(let existingTypeDescription):
209-
return renderedExistingTypeDescription(existingTypeDescription)
209+
renderExistingTypeDescription(existingTypeDescription)
210210
}
211211
}
212212

@@ -446,7 +446,7 @@ struct TextBasedRenderer: RendererProtocol {
446446
switch expression {
447447
case .literal(let literalDescription): renderLiteral(literalDescription)
448448
case .identifier(let identifierDescription):
449-
writer.writeLine(renderedIdentifier(identifierDescription))
449+
renderIdentifier(identifierDescription)
450450
case .memberAccess(let memberAccessDescription): renderMemberAccess(memberAccessDescription)
451451
case .functionCall(let functionCallDescription): renderFunctionCall(functionCallDescription)
452452
case .assignment(let assignment): renderAssignment(assignment)
@@ -534,20 +534,44 @@ struct TextBasedRenderer: RendererProtocol {
534534
}
535535

536536
/// Renders the specified type reference to an existing type.
537-
func renderedExistingTypeDescription(_ type: ExistingTypeDescription) -> String {
537+
func renderExistingTypeDescription(_ type: ExistingTypeDescription) {
538538
switch type {
539539
case .any(let existingTypeDescription):
540-
return "any \(renderedExistingTypeDescription(existingTypeDescription))"
540+
writer.writeLine("any ")
541+
writer.nextLineAppendsToLastLine()
542+
renderExistingTypeDescription(existingTypeDescription)
541543
case .generic(let wrapper, let wrapped):
542-
return
543-
"\(renderedExistingTypeDescription(wrapper))<\(renderedExistingTypeDescription(wrapped))>"
544+
renderExistingTypeDescription(wrapper)
545+
writer.nextLineAppendsToLastLine()
546+
writer.writeLine("<")
547+
writer.nextLineAppendsToLastLine()
548+
renderExistingTypeDescription(wrapped)
549+
writer.nextLineAppendsToLastLine()
550+
writer.writeLine(">")
544551
case .optional(let existingTypeDescription):
545-
return "\(renderedExistingTypeDescription(existingTypeDescription))?"
546-
case .member(let components): return components.joined(separator: ".")
552+
renderExistingTypeDescription(existingTypeDescription)
553+
writer.nextLineAppendsToLastLine()
554+
writer.writeLine("?")
555+
case .member(let components):
556+
writer.writeLine(components.joined(separator: "."))
547557
case .array(let existingTypeDescription):
548-
return "[\(renderedExistingTypeDescription(existingTypeDescription))]"
558+
writer.writeLine("[")
559+
writer.nextLineAppendsToLastLine()
560+
renderExistingTypeDescription(existingTypeDescription)
561+
writer.nextLineAppendsToLastLine()
562+
writer.writeLine("]")
549563
case .dictionaryValue(let existingTypeDescription):
550-
return "[String: \(renderedExistingTypeDescription(existingTypeDescription))]"
564+
writer.writeLine("[String: ")
565+
writer.nextLineAppendsToLastLine()
566+
renderExistingTypeDescription(existingTypeDescription)
567+
writer.nextLineAppendsToLastLine()
568+
writer.writeLine("]")
569+
case .some(let existingTypeDescription):
570+
writer.writeLine("some ")
571+
writer.nextLineAppendsToLastLine()
572+
renderExistingTypeDescription(existingTypeDescription)
573+
case .closure(let closureSignatureDescription):
574+
renderClosureSignature(closureSignatureDescription)
551575
}
552576
}
553577

@@ -558,9 +582,11 @@ struct TextBasedRenderer: RendererProtocol {
558582
words.append(renderedAccessModifier(accessModifier))
559583
}
560584
words.append(contentsOf: [
561-
"typealias", alias.name, "=", renderedExistingTypeDescription(alias.existingType),
585+
"typealias", alias.name, "=",
562586
])
563-
writer.writeLine(words.joinedWords())
587+
writer.writeLine(words.joinedWords() + " ")
588+
writer.nextLineAppendsToLastLine()
589+
renderExistingTypeDescription(alias.existingType)
564590
}
565591

566592
/// Renders the specified binding kind.
@@ -587,7 +613,9 @@ struct TextBasedRenderer: RendererProtocol {
587613
renderExpression(variable.left)
588614
if let type = variable.type {
589615
writer.nextLineAppendsToLastLine()
590-
writer.writeLine(": \(renderedExistingTypeDescription(type))")
616+
writer.writeLine(": ")
617+
writer.nextLineAppendsToLastLine()
618+
renderExistingTypeDescription(type)
591619
}
592620
}
593621

@@ -703,11 +731,12 @@ struct TextBasedRenderer: RendererProtocol {
703731
}
704732

705733
/// Renders the specified enum case associated value.
706-
func renderedEnumCaseAssociatedValue(_ value: EnumCaseAssociatedValueDescription) -> String {
734+
func renderEnumCaseAssociatedValue(_ value: EnumCaseAssociatedValueDescription) {
707735
var words: [String] = []
708736
if let label = value.label { words.append(label + ":") }
709-
words.append(renderedExistingTypeDescription(value.type))
710-
return words.joinedWords()
737+
writer.writeLine(words.joinedWords())
738+
writer.nextLineAppendsToLastLine()
739+
renderExistingTypeDescription(value.type)
711740
}
712741

713742
/// Renders the specified enum case declaration.
@@ -722,9 +751,13 @@ struct TextBasedRenderer: RendererProtocol {
722751
renderLiteral(rawValue)
723752
case .nameWithAssociatedValues(let values):
724753
if values.isEmpty { break }
725-
let associatedValues = values.map(renderedEnumCaseAssociatedValue).joined(separator: ", ")
726-
writer.nextLineAppendsToLastLine()
727-
writer.writeLine("(\(associatedValues))")
754+
for (value, isLast) in values.enumeratedWithLastMarker() {
755+
renderEnumCaseAssociatedValue(value)
756+
if !isLast {
757+
writer.nextLineAppendsToLastLine()
758+
writer.writeLine(", ")
759+
}
760+
}
728761
}
729762
}
730763

@@ -750,7 +783,9 @@ struct TextBasedRenderer: RendererProtocol {
750783
func renderedFunctionKind(_ functionKind: FunctionKind) -> String {
751784
switch functionKind {
752785
case .initializer(let isFailable): return "init\(isFailable ? "?" : "")"
753-
case .function(let name, let isStatic): return (isStatic ? "static " : "") + "func \(name)"
786+
case .function(let name, let isStatic):
787+
return (isStatic ? "static " : "") + "func \(name)"
788+
754789
}
755790
}
756791

@@ -759,6 +794,54 @@ struct TextBasedRenderer: RendererProtocol {
759794
switch keyword {
760795
case .throws: return "throws"
761796
case .async: return "async"
797+
case .rethrows: return "rethrows"
798+
}
799+
}
800+
801+
/// Renders the specified function signature.
802+
func renderClosureSignature(_ signature: ClosureSignatureDescription) {
803+
if signature.sendable {
804+
writer.writeLine("@Sendable ")
805+
writer.nextLineAppendsToLastLine()
806+
}
807+
if signature.escaping {
808+
writer.writeLine("@escaping ")
809+
writer.nextLineAppendsToLastLine()
810+
}
811+
812+
writer.writeLine("(")
813+
let parameters = signature.parameters
814+
let separateLines = parameters.count > 1
815+
if separateLines {
816+
writer.withNestedLevel {
817+
for (parameter, isLast) in signature.parameters.enumeratedWithLastMarker() {
818+
renderClosureParameter(parameter)
819+
if !isLast {
820+
writer.nextLineAppendsToLastLine()
821+
writer.writeLine(",")
822+
}
823+
}
824+
}
825+
} else {
826+
writer.nextLineAppendsToLastLine()
827+
if let parameter = parameters.first {
828+
renderClosureParameter(parameter)
829+
writer.nextLineAppendsToLastLine()
830+
}
831+
}
832+
writer.writeLine(")")
833+
834+
let keywords = signature.keywords
835+
for keyword in keywords {
836+
writer.nextLineAppendsToLastLine()
837+
writer.writeLine(" " + renderedFunctionKeyword(keyword))
838+
}
839+
840+
if let returnType = signature.returnType {
841+
writer.nextLineAppendsToLastLine()
842+
writer.writeLine(" -> ")
843+
writer.nextLineAppendsToLastLine()
844+
renderExpression(returnType)
762845
}
763846
}
764847

@@ -769,7 +852,26 @@ struct TextBasedRenderer: RendererProtocol {
769852
writer.writeLine(renderedAccessModifier(accessModifier) + " ")
770853
writer.nextLineAppendsToLastLine()
771854
}
772-
writer.writeLine(renderedFunctionKind(signature.kind) + "(")
855+
let generics = signature.generics
856+
writer.writeLine(
857+
renderedFunctionKind(signature.kind)
858+
)
859+
if !generics.isEmpty {
860+
writer.nextLineAppendsToLastLine()
861+
writer.writeLine("<")
862+
for (genericType, isLast) in generics.enumeratedWithLastMarker() {
863+
writer.nextLineAppendsToLastLine()
864+
renderExistingTypeDescription(genericType)
865+
if !isLast {
866+
writer.nextLineAppendsToLastLine()
867+
writer.writeLine(", ")
868+
}
869+
}
870+
writer.nextLineAppendsToLastLine()
871+
writer.writeLine(">")
872+
}
873+
writer.nextLineAppendsToLastLine()
874+
writer.writeLine("(")
773875
let parameters = signature.parameters
774876
let separateLines = parameters.count > 1
775877
if separateLines {
@@ -806,6 +908,11 @@ struct TextBasedRenderer: RendererProtocol {
806908
writer.nextLineAppendsToLastLine()
807909
renderExpression(returnType)
808910
}
911+
912+
if let whereClause = signature.whereClause {
913+
writer.nextLineAppendsToLastLine()
914+
writer.writeLine(" " + renderedWhereClause(whereClause))
915+
}
809916
}
810917

811918
/// Renders the specified function declaration.
@@ -839,11 +946,54 @@ struct TextBasedRenderer: RendererProtocol {
839946
}
840947
writer.writeLine(": ")
841948
writer.nextLineAppendsToLastLine()
949+
950+
if parameterDescription.inout {
951+
writer.writeLine("inout ")
952+
writer.nextLineAppendsToLastLine()
953+
}
954+
955+
if let type = parameterDescription.type {
956+
renderExistingTypeDescription(type)
957+
}
958+
959+
if let defaultValue = parameterDescription.defaultValue {
960+
writer.nextLineAppendsToLastLine()
961+
writer.writeLine(" = ")
962+
writer.nextLineAppendsToLastLine()
963+
renderExpression(defaultValue)
964+
}
965+
}
966+
967+
/// Renders the specified parameter declaration for a closure.
968+
func renderClosureParameter(_ parameterDescription: ParameterDescription) {
969+
let name = parameterDescription.name
970+
let label: String
971+
if let declaredLabel = parameterDescription.label {
972+
label = declaredLabel
973+
} else {
974+
label = "_"
975+
}
976+
977+
if let name = name {
978+
writer.writeLine(label)
979+
if name != parameterDescription.label {
980+
// If the label and name are the same value, don't repeat it.
981+
writer.writeLine(" ")
982+
writer.nextLineAppendsToLastLine()
983+
writer.writeLine(name)
984+
writer.nextLineAppendsToLastLine()
985+
}
986+
}
987+
842988
if parameterDescription.inout {
843989
writer.writeLine("inout ")
844990
writer.nextLineAppendsToLastLine()
845991
}
846-
writer.writeLine(renderedExistingTypeDescription(parameterDescription.type))
992+
993+
if let type = parameterDescription.type {
994+
renderExistingTypeDescription(type)
995+
}
996+
847997
if let defaultValue = parameterDescription.defaultValue {
848998
writer.nextLineAppendsToLastLine()
849999
writer.writeLine(" = ")

0 commit comments

Comments
 (0)