Skip to content

Commit 3e55dee

Browse files
authored
Merge pull request #3364 from square/jszumski/swift-codable-container-name-collision
Swift: Fix a naming collision if a oneof is called "container"
2 parents c7a6b0e + 95c51d5 commit 3e55dee

File tree

3 files changed

+33
-23
lines changed

3 files changed

+33
-23
lines changed

wire-swift-generator/src/main/java/com/squareup/wire/swift/SwiftGenerator.kt

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -849,12 +849,15 @@ class SwiftGenerator private constructor(
849849

850850
// We cannot rely upon built-in Codable support since we need to support multiple keys.
851851
if (type.declaredFieldsAndOneOfFields.isNotEmpty()) {
852+
// check for name collisions
853+
val container = if ("container" in type.declaredFieldsAndOneOfFields.map { it.name }) "_container" else "container"
854+
852855
addFunction(
853856
FunctionSpec.constructorBuilder()
854857
.addParameter("from", "decoder", decoder)
855858
.addModifiers(PUBLIC)
856859
.throws(true)
857-
.addStatement("let container = try decoder.container(keyedBy: %T.self)", codingKeys)
860+
.addStatement("let $container = try decoder.container(keyedBy: %T.self)", codingKeys)
858861
.apply {
859862
type.declaredFields.forEach { field ->
860863
val hasPropertyWrapper = !isIndirect(type, field) && (field.defaultedValue != null || field.isProtoDefaulted)
@@ -891,7 +894,7 @@ class SwiftGenerator private constructor(
891894
val fieldName = if (hasPropertyWrapper) { "_${field.safeName}" } else { field.safeName }
892895
val prefix = if (hasPropertyWrapper) { "self.%1N.wrappedValue" } else { "self.%1N" }
893896
addStatement(
894-
"$prefix = try container.$decode($typeArg%2T.self, $forKeys: $keys)",
897+
"$prefix = try $container.$decode($typeArg%2T.self, $forKeys: $keys)",
895898
fieldName,
896899
typeName,
897900
)
@@ -916,15 +919,15 @@ class SwiftGenerator private constructor(
916919
if (index == 0) {
917920
beginControlFlow(
918921
"if",
919-
"let %1N = try container.decodeIfPresent(%2T.self, forKey: %3S)",
922+
"let %1N = try $container.decodeIfPresent(%2T.self, forKey: %3S)",
920923
fieldName,
921924
typeName,
922925
keyName,
923926
)
924927
} else {
925928
nextControlFlow(
926929
"else if",
927-
"let %1N = try container.decodeIfPresent(%2T.self, forKey: %3S)",
930+
"let %1N = try $container.decodeIfPresent(%2T.self, forKey: %3S)",
928931
fieldName,
929932
typeName,
930933
keyName,
@@ -944,7 +947,7 @@ class SwiftGenerator private constructor(
944947
.addParameter("to", "encoder", encoder)
945948
.addModifiers(PUBLIC)
946949
.throws(true)
947-
.addStatement("var container = encoder.container(keyedBy: %T.self)", codingKeys)
950+
.addStatement("var $container = encoder.container(keyedBy: %T.self)", codingKeys)
948951
.apply {
949952
if (type.declaredFieldsAndOneOfFields.any { it.codableName != null }) {
950953
addStatement("let preferCamelCase = encoder.protoKeyNameEncodingStrategy == .camelCase")
@@ -979,7 +982,7 @@ class SwiftGenerator private constructor(
979982
} ?: Pair("%2S", arrayOf(field.name))
980983

981984
addStatement(
982-
"try container.$encode(${typeArg}self.%1N, forKey: $keys)",
985+
"try $container.$encode(${typeArg}self.%1N, forKey: $keys)",
983986
field.safeName,
984987
*args,
985988
)
@@ -1022,7 +1025,7 @@ class SwiftGenerator private constructor(
10221025
} ?: Pair("%2S", arrayOf(field.name))
10231026

10241027
addStatement(
1025-
"case .%1N(let %1N): try container.encode(%1N, forKey: $keys)",
1028+
"case .%1N(let %1N): try $container.encode(%1N, forKey: $keys)",
10261029
field.safeName,
10271030
*args,
10281031
)

wire-tests-swift/no-manifest/src/main/swift/Screen.swift

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ extension Screen : Proto2Codable {
5656
case 3: screen = .screen_oneof_sub_message(try protoReader.decode(Screen.SubMessage.self))
5757
case 4: screen = .`self`(try protoReader.decode(Screen.Self_.self))
5858
case 5: view = .view_oneof_string(try protoReader.decode(String.self))
59+
case 6: view = .container(try protoReader.decode(String.self))
5960
default: try protoReader.readUnknownField(tag: tag)
6061
}
6162
}
@@ -81,46 +82,49 @@ extension Screen : Proto2Codable {
8182
extension Screen : Codable {
8283

8384
public init(from decoder: Decoder) throws {
84-
let container = try decoder.container(keyedBy: StringLiteralCodingKeys.self)
85-
if let screen_oneof_string = try container.decodeIfPresent(String.self, forKey: "screenOneofString") {
85+
let _container = try decoder.container(keyedBy: StringLiteralCodingKeys.self)
86+
if let screen_oneof_string = try _container.decodeIfPresent(String.self, forKey: "screenOneofString") {
8687
self.screen = .screen_oneof_string(screen_oneof_string)
87-
} else if let screen_oneof_string = try container.decodeIfPresent(String.self, forKey: "screen_oneof_string") {
88+
} else if let screen_oneof_string = try _container.decodeIfPresent(String.self, forKey: "screen_oneof_string") {
8889
self.screen = .screen_oneof_string(screen_oneof_string)
89-
} else if let screen_oneof_int32 = try container.decodeIfPresent(Int32.self, forKey: "screenOneofInt32") {
90+
} else if let screen_oneof_int32 = try _container.decodeIfPresent(Int32.self, forKey: "screenOneofInt32") {
9091
self.screen = .screen_oneof_int32(screen_oneof_int32)
91-
} else if let screen_oneof_int32 = try container.decodeIfPresent(Int32.self, forKey: "screen_oneof_int32") {
92+
} else if let screen_oneof_int32 = try _container.decodeIfPresent(Int32.self, forKey: "screen_oneof_int32") {
9293
self.screen = .screen_oneof_int32(screen_oneof_int32)
93-
} else if let screen_oneof_sub_message = try container.decodeIfPresent(Screen.SubMessage.self, forKey: "screenOneofSubMessage") {
94+
} else if let screen_oneof_sub_message = try _container.decodeIfPresent(Screen.SubMessage.self, forKey: "screenOneofSubMessage") {
9495
self.screen = .screen_oneof_sub_message(screen_oneof_sub_message)
95-
} else if let screen_oneof_sub_message = try container.decodeIfPresent(Screen.SubMessage.self, forKey: "screen_oneof_sub_message") {
96+
} else if let screen_oneof_sub_message = try _container.decodeIfPresent(Screen.SubMessage.self, forKey: "screen_oneof_sub_message") {
9697
self.screen = .screen_oneof_sub_message(screen_oneof_sub_message)
97-
} else if let self_ = try container.decodeIfPresent(Screen.Self_.self, forKey: "self") {
98+
} else if let self_ = try _container.decodeIfPresent(Screen.Self_.self, forKey: "self") {
9899
self.screen = .`self`(self_)
99100
} else {
100101
self.screen = nil
101102
}
102-
if let view_oneof_string = try container.decodeIfPresent(String.self, forKey: "viewOneofString") {
103+
if let view_oneof_string = try _container.decodeIfPresent(String.self, forKey: "viewOneofString") {
103104
self.view = .view_oneof_string(view_oneof_string)
104-
} else if let view_oneof_string = try container.decodeIfPresent(String.self, forKey: "view_oneof_string") {
105+
} else if let view_oneof_string = try _container.decodeIfPresent(String.self, forKey: "view_oneof_string") {
105106
self.view = .view_oneof_string(view_oneof_string)
107+
} else if let container = try _container.decodeIfPresent(String.self, forKey: "container") {
108+
self.view = .container(container)
106109
} else {
107110
self.view = nil
108111
}
109112
}
110113

111114
public func encode(to encoder: Encoder) throws {
112-
var container = encoder.container(keyedBy: StringLiteralCodingKeys.self)
115+
var _container = encoder.container(keyedBy: StringLiteralCodingKeys.self)
113116
let preferCamelCase = encoder.protoKeyNameEncodingStrategy == .camelCase
114117

115118
switch self.screen {
116-
case .screen_oneof_string(let screen_oneof_string): try container.encode(screen_oneof_string, forKey: preferCamelCase ? "screenOneofString" : "screen_oneof_string")
117-
case .screen_oneof_int32(let screen_oneof_int32): try container.encode(screen_oneof_int32, forKey: preferCamelCase ? "screenOneofInt32" : "screen_oneof_int32")
118-
case .screen_oneof_sub_message(let screen_oneof_sub_message): try container.encode(screen_oneof_sub_message, forKey: preferCamelCase ? "screenOneofSubMessage" : "screen_oneof_sub_message")
119-
case .`self`(let `self`): try container.encode(`self`, forKey: "self")
119+
case .screen_oneof_string(let screen_oneof_string): try _container.encode(screen_oneof_string, forKey: preferCamelCase ? "screenOneofString" : "screen_oneof_string")
120+
case .screen_oneof_int32(let screen_oneof_int32): try _container.encode(screen_oneof_int32, forKey: preferCamelCase ? "screenOneofInt32" : "screen_oneof_int32")
121+
case .screen_oneof_sub_message(let screen_oneof_sub_message): try _container.encode(screen_oneof_sub_message, forKey: preferCamelCase ? "screenOneofSubMessage" : "screen_oneof_sub_message")
122+
case .`self`(let `self`): try _container.encode(`self`, forKey: "self")
120123
case Optional.none: break
121124
}
122125
switch self.view {
123-
case .view_oneof_string(let view_oneof_string): try container.encode(view_oneof_string, forKey: preferCamelCase ? "viewOneofString" : "view_oneof_string")
126+
case .view_oneof_string(let view_oneof_string): try _container.encode(view_oneof_string, forKey: preferCamelCase ? "viewOneofString" : "view_oneof_string")
127+
case .container(let container): try _container.encode(container, forKey: "container")
124128
case Optional.none: break
125129
}
126130
}
@@ -154,10 +158,12 @@ extension Screen {
154158
public enum View {
155159

156160
case view_oneof_string(String)
161+
case container(String)
157162

158163
fileprivate func encode(to protoWriter: ProtoWriter) throws {
159164
switch self {
160165
case .view_oneof_string(let view_oneof_string): try protoWriter.encode(tag: 5, value: view_oneof_string)
166+
case .container(let container): try protoWriter.encode(tag: 6, value: container)
161167
}
162168
}
163169

wire-tests/src/commonTest/proto/kotlin/swift_edge_cases.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ message Screen {
4343

4444
oneof view {
4545
string view_oneof_string = 5;
46+
string container = 6;
4647
}
4748

4849
message Self {}

0 commit comments

Comments
 (0)