Skip to content

Commit b6de8a1

Browse files
authored
Move ContentType.identifier logic into the translator (#141)
Move ContentType.identifier logic into the translator ### Motivation In preparation for changing the mapping of content type names onto enum case names, we need to have the `ContentType.identifier` logic on a translator, which has access to the feature flags, so that we can later conditionalize the logic. ### Modifications Takes the first step - moves the existing logic onto the translator. ### Result NFC ### Test Plan Added unit tests both for the existing logic, and also for the stubbed out logic behind the feature flag. Reviewed by: simonjbeaumont Builds: ✔︎ pull request validation (5.8) - Build finished. ✔︎ pull request validation (5.9) - Build finished. ✔︎ pull request validation (docc test) - Build finished. ✔︎ pull request validation (integration test) - Build finished. ✔︎ pull request validation (nightly) - Build finished. ✔︎ pull request validation (soundness) - Build finished. #141
1 parent 22a7d7a commit b6de8a1

File tree

8 files changed

+111
-24
lines changed

8 files changed

+111
-24
lines changed

Sources/_OpenAPIGeneratorCore/Translator/Content/ContentInspector.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ extension FileTranslator {
5252
else {
5353
return nil
5454
}
55-
let identifier = content.contentType.identifier
55+
let identifier = contentSwiftName(content.contentType)
5656
let associatedType = try TypeAssigner.typeUsage(
5757
usingNamingHint: identifier,
5858
withSchema: content.schema,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftOpenAPIGenerator open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
import OpenAPIKit30
15+
16+
extension FileTranslator {
17+
18+
/// Returns a Swift-safe identifier used as the name of the content
19+
/// enum case.
20+
///
21+
/// - Parameter contentType: The content type for which to compute the name.
22+
func contentSwiftName(_ contentType: ContentType) -> String {
23+
if config.featureFlags.contains(.multipleContentTypes) {
24+
return "unsupported"
25+
} else {
26+
switch contentType {
27+
case .json:
28+
return "json"
29+
case .text:
30+
return "text"
31+
case .binary:
32+
return "binary"
33+
}
34+
}
35+
}
36+
}

Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,6 @@ enum ContentType: Hashable {
6969
}
7070
}
7171

72-
/// An identifier used as the Payload.Content enum case name
73-
/// in generated code.
74-
var identifier: String {
75-
switch self {
76-
case .json:
77-
return "json"
78-
case .text:
79-
return "text"
80-
case .binary:
81-
return "binary"
82-
}
83-
}
84-
8572
/// The coding strategy appropriate for this content type.
8673
var codingStrategy: CodingStrategy {
8774
switch self {

Sources/_OpenAPIGeneratorCore/Translator/RequestBody/translateRequestBody.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ extension TypesFileTranslator {
5656
)
5757
bodyMembers.append(contentsOf: inlineTypeDecls)
5858
}
59-
let identifier = content.content.contentType.identifier
59+
let identifier = contentSwiftName(content.content.contentType)
6060
let associatedType = content.resolvedTypeUsage
6161
let contentCase: Declaration = .enumCase(
6262
.init(
@@ -178,7 +178,7 @@ extension ClientFileTranslator {
178178
let typedContent = requestBody.content
179179
let content = typedContent.content
180180
let contentType = content.contentType
181-
let contentTypeIdentifier = contentType.identifier
181+
let contentTypeIdentifier = contentSwiftName(contentType)
182182
let contentTypeHeaderValue = contentType.headerValueForSending
183183

184184
let transformReturnExpr: Expression = .return(
@@ -270,7 +270,7 @@ extension ServerFileTranslator {
270270
let contentTypeUsage = typedContent.resolvedTypeUsage
271271
let content = typedContent.content
272272
let contentType = content.contentType
273-
let contentTypeIdentifier = contentType.identifier
273+
let contentTypeIdentifier = contentSwiftName(contentType)
274274
let codingStrategyName = contentType.codingStrategy.runtimeName
275275
let isOptional = !requestBody.request.required
276276

Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponse.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ extension TypesFileTranslator {
6363
response.content,
6464
inParent: bodyTypeName
6565
) {
66-
let identifier = typedContent.content.contentType.identifier
66+
let identifier = contentSwiftName(typedContent.content.contentType)
6767
let associatedType = typedContent.resolvedTypeUsage
6868
if TypeMatcher.isInlinable(typedContent.content.schema), let inlineType = typedContent.typeUsage {
6969
let inlineTypeDecls = try translateSchema(

Sources/_OpenAPIGeneratorCore/Translator/Responses/translateResponseOutcome.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ extension ClientFileTranslator {
169169
argumentNames: ["value"],
170170
body: [
171171
.expression(
172-
.dot(typedContent.content.contentType.identifier)
172+
.dot(contentSwiftName(typedContent.content.contentType))
173173
.call([
174174
.init(label: nil, expression: .identifier("value"))
175175
])
@@ -323,7 +323,7 @@ extension ServerFileTranslator {
323323
let contentType = typedContent.content.contentType
324324
let switchContentCases: [SwitchCaseDescription] = [
325325
.init(
326-
kind: .case(.dot(contentType.identifier), ["value"]),
326+
kind: .case(.dot(contentSwiftName(contentType)), ["value"]),
327327
body: [
328328
.expression(
329329
.return(

Tests/OpenAPIGeneratorCoreTests/TestUtilities.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,26 @@ class Test_Core: XCTestCase {
2525

2626
func makeTranslator(
2727
components: OpenAPI.Components = .noComponents,
28-
diagnostics: any DiagnosticCollector = PrintingDiagnosticCollector()
28+
diagnostics: any DiagnosticCollector = PrintingDiagnosticCollector(),
29+
featureFlags: FeatureFlags = []
2930
) -> any FileTranslator {
3031
makeTypesTranslator(
3132
components: components,
32-
diagnostics: diagnostics
33+
diagnostics: diagnostics,
34+
featureFlags: featureFlags
3335
)
3436
}
3537

3638
func makeTypesTranslator(
3739
components: OpenAPI.Components = .noComponents,
38-
diagnostics: any DiagnosticCollector = PrintingDiagnosticCollector()
40+
diagnostics: any DiagnosticCollector = PrintingDiagnosticCollector(),
41+
featureFlags: FeatureFlags = []
3942
) -> TypesFileTranslator {
4043
TypesFileTranslator(
41-
config: .init(mode: .types),
44+
config: .init(
45+
mode: .types,
46+
featureFlags: featureFlags
47+
),
4248
diagnostics: diagnostics,
4349
components: components
4450
)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftOpenAPIGenerator open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
import XCTest
15+
import OpenAPIKit30
16+
@testable import _OpenAPIGeneratorCore
17+
18+
final class Test_ContentSwiftName: Test_Core {
19+
20+
func testExisting() throws {
21+
let nameMaker = makeTranslator(featureFlags: []).contentSwiftName
22+
let cases: [(String, String)] = [
23+
("application/json", "json"),
24+
("application/x-www-form-urlencoded", "binary"),
25+
("multipart/form-data", "binary"),
26+
("text/plain", "text"),
27+
("*/*", "binary"),
28+
("application/xml", "binary"),
29+
("application/octet-stream", "binary"),
30+
("application/myformat+json", "json"),
31+
("foo/bar", "binary"),
32+
]
33+
try _testIdentifiers(cases: cases, nameMaker: nameMaker)
34+
}
35+
36+
func testProposed() throws {
37+
let nameMaker = makeTranslator(featureFlags: [.multipleContentTypes]).contentSwiftName
38+
let cases: [(String, String)] = [
39+
("application/json", "unsupported"),
40+
("application/x-www-form-urlencoded", "unsupported"),
41+
("multipart/form-data", "unsupported"),
42+
("text/plain", "unsupported"),
43+
("*/*", "unsupported"),
44+
("application/xml", "unsupported"),
45+
("application/octet-stream", "unsupported"),
46+
("application/myformat+json", "unsupported"),
47+
("foo/bar", "unsupported"),
48+
]
49+
try _testIdentifiers(cases: cases, nameMaker: nameMaker)
50+
}
51+
52+
func _testIdentifiers(cases: [(String, String)], nameMaker: (ContentType) -> String) throws {
53+
for item in cases {
54+
let contentType = try XCTUnwrap(ContentType(item.0))
55+
XCTAssertEqual(nameMaker(contentType), item.1, "Case \(item.0) failed")
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)