Skip to content

Commit 5dd8d18

Browse files
Use self for member access/assignment in all initializers, decoders, and encoders (#700)
### Motivation In order to address #695 we made some targeted fixes (#696, #699) to use explicit-self to avoid clashing with schema property names. This addressed a clash with a specific variable with properties of only certain schemas, but there are more places where we might encounter future issues. Specifically, we have other variable names which might cause a clash (e.g. `storage` and `discriminator`), and there are other flavours of initializers, encoders, and decoders that were not updated in the targeted fix. In this PR, we update all access and assignment in the generated code dealing with schemas to use explicit-self. ### Modifications - Use self for member access and assignment in all initializers, decoders, and encoders. - Update the reference tests and snippet tests. ### Result Removed some cases where valid OpenAPI docs would produce non-compiling code. ### Test Plan Snippet and reference tests. The latter is actually compiled during the CI.
1 parent 2e1b6fc commit 5dd8d18

File tree

5 files changed

+170
-167
lines changed

5 files changed

+170
-167
lines changed

Sources/_OpenAPIGeneratorCore/Layers/StructuredSwiftRepresentation.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,16 @@ extension Expression {
13541354
/// - Returns: A new expression representing member access with a dot prefix.
13551355
static func dot(_ member: String) -> Self { Self.memberAccess(.init(right: member)) }
13561356

1357+
/// Returns a new member access expression with `self` as the receiver.
1358+
///
1359+
/// For example: `self.foo`, where `member` is `foo`.
1360+
///
1361+
/// - Parameter member: The name of the member to access on the expression.
1362+
/// - Returns: A new expression representing member access.
1363+
static func selfDot(_ member: String) -> Expression {
1364+
.memberAccess(.init(left: .identifier(.pattern("self")), right: member))
1365+
}
1366+
13571367
/// Returns a new identifier expression for the provided pattern, such
13581368
/// as a variable or function name.
13591369
/// - Parameter name: The name of the identifier.
@@ -1555,6 +1565,7 @@ extension Expression {
15551565
/// - Parameter expressions: The member expressions.
15561566
/// - Returns: A tuple expression.
15571567
static func tuple(_ expressions: [Expression]) -> Self { .tuple(.init(members: expressions)) }
1568+
15581569
}
15591570

15601571
extension MemberAccessDescription {

Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateCodable.swift

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ extension FileTranslator {
118118
let assignExprs: [Expression] = properties.map { property in
119119
let typeUsage = property.typeUsage
120120
return .assignment(
121-
left: .identifierPattern("self").dot(property.swiftSafeName),
121+
left: .selfDot(property.swiftSafeName),
122122
right: .try(
123123
.identifierPattern("container").dot("decode\(typeUsage.isOptional ? "IfPresent" : "")")
124124
.call([
@@ -156,7 +156,7 @@ extension FileTranslator {
156156
.try(
157157
.identifierPattern("container").dot("encode\(property.typeUsage.isOptional ? "IfPresent" : "")")
158158
.call([
159-
.init(label: nil, expression: .identifierPattern("self").dot(property.swiftSafeName)),
159+
.init(label: nil, expression: .selfDot(property.swiftSafeName)),
160160
.init(label: "forKey", expression: .dot(property.swiftSafeName)),
161161
])
162162
)
@@ -181,7 +181,7 @@ extension FileTranslator {
181181
let assignExprs: [Expression] = properties.map { property, isKeyValuePair in
182182
let decoderExpr: Expression =
183183
isKeyValuePair ? .initFromDecoderExpr() : .decodeFromSingleValueContainerExpr()
184-
return .assignment(left: .identifierPattern(property.swiftSafeName), right: .try(decoderExpr))
184+
return .assignment(left: .selfDot(property.swiftSafeName), right: .try(decoderExpr))
185185
}
186186
return decoderInitializer(body: assignExprs.map { .expression($0) })
187187
}
@@ -194,12 +194,11 @@ extension FileTranslator {
194194
{
195195
let exprs: [Expression]
196196
if let firstSingleValue = properties.first(where: { !$0.isKeyValuePair }) {
197-
let expr: Expression = .identifierPattern(firstSingleValue.property.swiftSafeName)
197+
let expr: Expression = .selfDot(firstSingleValue.property.swiftSafeName)
198198
.encodeToSingleValueContainerExpr(gracefully: false)
199199
exprs = [expr]
200200
} else {
201-
exprs = properties.filter { $0.isKeyValuePair }.map(\.property.swiftSafeName)
202-
.map { name in .identifierPattern(name).encodeExpr() }
201+
exprs = properties.filter(\.isKeyValuePair).map { .selfDot($0.property.swiftSafeName).encodeExpr() }
203202
}
204203
return encoderFunction(body: exprs.map { .expression($0) })
205204
}
@@ -216,18 +215,15 @@ extension FileTranslator {
216215
let assignBlocks: [CodeBlock] = properties.map { (property, isKeyValuePair) in
217216
let decoderExpr: Expression =
218217
isKeyValuePair ? .initFromDecoderExpr() : .decodeFromSingleValueContainerExpr()
219-
let assignExpr: Expression = .assignment(
220-
left: .identifierPattern(property.swiftSafeName),
221-
right: .try(decoderExpr)
222-
)
218+
let assignExpr: Expression = .assignment(left: .selfDot(property.swiftSafeName), right: .try(decoderExpr))
223219
return .expression(assignExpr.wrapInDoCatchAppendArrayExpr())
224220
}
225221
let atLeastOneNotNilCheckExpr: Expression = .try(
226222
.identifierType(TypeName.decodingError).dot("verifyAtLeastOneSchemaIsNotNil")
227223
.call([
228224
.init(
229225
label: nil,
230-
expression: .literal(.array(properties.map { .identifierPattern($0.property.swiftSafeName) }))
226+
expression: .literal(.array(properties.map { .selfDot($0.property.swiftSafeName) }))
231227
), .init(label: "type", expression: .identifierPattern("Self").dot("self")),
232228
.init(label: "codingPath", expression: .identifierPattern("decoder").dot("codingPath")),
233229
.init(label: "errors", expression: .identifierPattern("errors")),
@@ -250,14 +246,12 @@ extension FileTranslator {
250246
? nil
251247
: .try(
252248
.identifierPattern("encoder").dot("encodeFirstNonNilValueToSingleValueContainer")
253-
.call([
254-
.init(label: nil, expression: .literal(.array(singleValueNames.map { .identifierPattern($0) })))
255-
])
249+
.call([.init(label: nil, expression: .literal(.array(singleValueNames.map { .selfDot($0) })))])
256250
)
257251
let encodeExprs: [Expression] =
258252
(encodeSingleValuesExpr.flatMap { [$0] } ?? [])
259253
+ properties.filter { $0.isKeyValuePair }.map(\.property)
260-
.map { property in .identifierPattern(property.swiftSafeName).optionallyChained().encodeExpr() }
254+
.map { property in .selfDot(property.swiftSafeName).optionallyChained().encodeExpr() }
261255
return encoderFunction(body: encodeExprs.map { .expression($0) })
262256
}
263257

Sources/_OpenAPIGeneratorCore/Translator/TypesTranslator/translateBoxedTypes.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,8 @@ extension TypesFileTranslator {
107107
case .variable(var variableDescription) = commented
108108
else { return member }
109109
let name = TextBasedRenderer.renderedExpressionAsString(variableDescription.left)
110-
variableDescription.getter = [.expression(.identifierPattern("storage").dot("value").dot(name))]
111-
variableDescription.modify = [
112-
.expression(.yield(.inOut(.identifierPattern("storage").dot("value").dot(name))))
113-
]
110+
variableDescription.getter = [.expression(.selfDot("storage").dot("value").dot(name))]
111+
variableDescription.modify = [.expression(.yield(.inOut(.selfDot("storage").dot("value").dot(name))))]
114112
return .commentable(comment, .variable(variableDescription))
115113
}
116114

@@ -127,7 +125,7 @@ extension TypesFileTranslator {
127125
funcDesc.body = [
128126
.expression(
129127
.assignment(
130-
left: .identifierPattern("storage"),
128+
left: .selfDot("storage"),
131129
right: .dot("init")
132130
.call([
133131
.init(
@@ -167,7 +165,7 @@ extension TypesFileTranslator {
167165
body: [
168166
.expression(
169167
.assignment(
170-
left: .identifierPattern("storage"),
168+
left: .selfDot("storage"),
171169
right: .try(
172170
.dot("init").call([.init(label: "from", expression: .identifierPattern("decoder"))])
173171
)
@@ -185,7 +183,7 @@ extension TypesFileTranslator {
185183
body: [
186184
.expression(
187185
.try(
188-
.identifierPattern("storage").dot("encode")
186+
.selfDot("storage").dot("encode")
189187
.call([.init(label: "to", expression: .identifierPattern("encoder"))])
190188
)
191189
)

0 commit comments

Comments
 (0)