Skip to content

Commit 76073a2

Browse files
authored
Extend structured swift to support generic structs (#2154)
Motivation: The structured swift representation we're using doesn't support generic struct at the moment. We'll need this for an upcoming change. Modifications: - Allow for generic structs with where clauses to be represented and rendered. Result: Generic structs can be rendered
1 parent 560c6c7 commit 76073a2

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

Sources/GRPCCodeGen/Internal/Renderer/TextBasedRenderer.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,10 +740,31 @@ struct TextBasedRenderer: RendererProtocol {
740740
}
741741
writer.writeLine("struct \(structDesc.name)")
742742
writer.nextLineAppendsToLastLine()
743+
let generics = structDesc.generics
744+
if !generics.isEmpty {
745+
writer.nextLineAppendsToLastLine()
746+
writer.writeLine("<")
747+
for (genericType, isLast) in generics.enumeratedWithLastMarker() {
748+
writer.nextLineAppendsToLastLine()
749+
renderExistingTypeDescription(genericType)
750+
if !isLast {
751+
writer.nextLineAppendsToLastLine()
752+
writer.writeLine(", ")
753+
}
754+
}
755+
writer.nextLineAppendsToLastLine()
756+
writer.writeLine(">")
757+
writer.nextLineAppendsToLastLine()
758+
}
743759
if !structDesc.conformances.isEmpty {
744760
writer.writeLine(": \(structDesc.conformances.joined(separator: ", "))")
745761
writer.nextLineAppendsToLastLine()
746762
}
763+
if let whereClause = structDesc.whereClause {
764+
writer.nextLineAppendsToLastLine()
765+
writer.writeLine(" " + renderedWhereClause(whereClause))
766+
writer.nextLineAppendsToLastLine()
767+
}
747768
writer.writeLine(" {")
748769
if !structDesc.members.isEmpty {
749770
writer.withNestedLevel {

Sources/GRPCCodeGen/Internal/StructuredSwiftRepresentation.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,11 +401,17 @@ struct StructDescription: Equatable, Codable, Sendable {
401401
/// For example, in `struct Foo {`, `name` is `Foo`.
402402
var name: String
403403

404+
/// The generic types of the struct.
405+
var generics: [ExistingTypeDescription] = []
406+
404407
/// The type names that the struct conforms to.
405408
///
406409
/// For example: `["Sendable", "Codable"]`.
407410
var conformances: [String] = []
408411

412+
/// A where clause constraining the struct declaration.
413+
var whereClause: WhereClause? = nil
414+
409415
/// The declarations that make up the main struct body.
410416
var members: [Declaration] = []
411417
}

Tests/GRPCCodeGenTests/Internal/Renderer/TextBasedRendererTests.swift

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,12 +820,62 @@ final class Test_TextBasedRenderer: XCTestCase {
820820
821821
func testStruct() throws {
822822
try _test(
823-
.init(name: "Structy"),
823+
StructDescription(name: "Structy"),
824824
renderedBy: { $0.renderStruct(_:) },
825825
rendersAs: #"""
826826
struct Structy {}
827827
"""#
828828
)
829+
try _test(
830+
StructDescription(
831+
name: "Structy",
832+
conformances: ["Foo"]
833+
),
834+
renderedBy: { $0.renderStruct(_:) },
835+
rendersAs: #"""
836+
struct Structy: Foo {}
837+
"""#
838+
)
839+
try _test(
840+
StructDescription(
841+
name: "Structy",
842+
generics: [.member("T")]
843+
),
844+
renderedBy: { $0.renderStruct(_:) },
845+
rendersAs: #"""
846+
struct Structy<T> {}
847+
"""#
848+
)
849+
try _test(
850+
StructDescription(
851+
name: "Structy",
852+
generics: [.member("T")],
853+
whereClause: WhereClause(
854+
requirements: [
855+
.conformance("T", "Foo"),
856+
.conformance("T", "Sendable"),
857+
]
858+
)
859+
),
860+
renderedBy: {
861+
$0.renderStruct(_:)
862+
},
863+
rendersAs: #"""
864+
struct Structy<T> where T: Foo, T: Sendable {}
865+
"""#
866+
)
867+
try _test(
868+
StructDescription(
869+
name: "Structy",
870+
generics: [.member("T")],
871+
conformances: ["Hashable"],
872+
whereClause: WhereClause(requirements: [.conformance("T", "Foo")])
873+
),
874+
renderedBy: { $0.renderStruct(_:) },
875+
rendersAs: #"""
876+
struct Structy<T>: Hashable where T: Foo {}
877+
"""#
878+
)
829879
}
830880
831881
func testProtocol() throws {

0 commit comments

Comments
 (0)