Skip to content

Commit

Permalink
Move ContentType.identifier logic into the translator (#141)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
czechboy0 authored Jul 26, 2023
1 parent 22a7d7a commit b6de8a1
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ extension FileTranslator {
else {
return nil
}
let identifier = content.contentType.identifier
let identifier = contentSwiftName(content.contentType)
let associatedType = try TypeAssigner.typeUsage(
usingNamingHint: identifier,
withSchema: content.schema,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftOpenAPIGenerator open source project
//
// Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30

extension FileTranslator {

/// Returns a Swift-safe identifier used as the name of the content
/// enum case.
///
/// - Parameter contentType: The content type for which to compute the name.
func contentSwiftName(_ contentType: ContentType) -> String {
if config.featureFlags.contains(.multipleContentTypes) {
return "unsupported"
} else {
switch contentType {
case .json:
return "json"
case .text:
return "text"
case .binary:
return "binary"
}
}
}
}
13 changes: 0 additions & 13 deletions Sources/_OpenAPIGeneratorCore/Translator/Content/ContentType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,6 @@ enum ContentType: Hashable {
}
}

/// An identifier used as the Payload.Content enum case name
/// in generated code.
var identifier: String {
switch self {
case .json:
return "json"
case .text:
return "text"
case .binary:
return "binary"
}
}

/// The coding strategy appropriate for this content type.
var codingStrategy: CodingStrategy {
switch self {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ extension TypesFileTranslator {
)
bodyMembers.append(contentsOf: inlineTypeDecls)
}
let identifier = content.content.contentType.identifier
let identifier = contentSwiftName(content.content.contentType)
let associatedType = content.resolvedTypeUsage
let contentCase: Declaration = .enumCase(
.init(
Expand Down Expand Up @@ -178,7 +178,7 @@ extension ClientFileTranslator {
let typedContent = requestBody.content
let content = typedContent.content
let contentType = content.contentType
let contentTypeIdentifier = contentType.identifier
let contentTypeIdentifier = contentSwiftName(contentType)
let contentTypeHeaderValue = contentType.headerValueForSending

let transformReturnExpr: Expression = .return(
Expand Down Expand Up @@ -270,7 +270,7 @@ extension ServerFileTranslator {
let contentTypeUsage = typedContent.resolvedTypeUsage
let content = typedContent.content
let contentType = content.contentType
let contentTypeIdentifier = contentType.identifier
let contentTypeIdentifier = contentSwiftName(contentType)
let codingStrategyName = contentType.codingStrategy.runtimeName
let isOptional = !requestBody.request.required

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ extension TypesFileTranslator {
response.content,
inParent: bodyTypeName
) {
let identifier = typedContent.content.contentType.identifier
let identifier = contentSwiftName(typedContent.content.contentType)
let associatedType = typedContent.resolvedTypeUsage
if TypeMatcher.isInlinable(typedContent.content.schema), let inlineType = typedContent.typeUsage {
let inlineTypeDecls = try translateSchema(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ extension ClientFileTranslator {
argumentNames: ["value"],
body: [
.expression(
.dot(typedContent.content.contentType.identifier)
.dot(contentSwiftName(typedContent.content.contentType))
.call([
.init(label: nil, expression: .identifier("value"))
])
Expand Down Expand Up @@ -323,7 +323,7 @@ extension ServerFileTranslator {
let contentType = typedContent.content.contentType
let switchContentCases: [SwitchCaseDescription] = [
.init(
kind: .case(.dot(contentType.identifier), ["value"]),
kind: .case(.dot(contentSwiftName(contentType)), ["value"]),
body: [
.expression(
.return(
Expand Down
14 changes: 10 additions & 4 deletions Tests/OpenAPIGeneratorCoreTests/TestUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,26 @@ class Test_Core: XCTestCase {

func makeTranslator(
components: OpenAPI.Components = .noComponents,
diagnostics: any DiagnosticCollector = PrintingDiagnosticCollector()
diagnostics: any DiagnosticCollector = PrintingDiagnosticCollector(),
featureFlags: FeatureFlags = []
) -> any FileTranslator {
makeTypesTranslator(
components: components,
diagnostics: diagnostics
diagnostics: diagnostics,
featureFlags: featureFlags
)
}

func makeTypesTranslator(
components: OpenAPI.Components = .noComponents,
diagnostics: any DiagnosticCollector = PrintingDiagnosticCollector()
diagnostics: any DiagnosticCollector = PrintingDiagnosticCollector(),
featureFlags: FeatureFlags = []
) -> TypesFileTranslator {
TypesFileTranslator(
config: .init(mode: .types),
config: .init(
mode: .types,
featureFlags: featureFlags
),
diagnostics: diagnostics,
components: components
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftOpenAPIGenerator open source project
//
// Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import XCTest
import OpenAPIKit30
@testable import _OpenAPIGeneratorCore

final class Test_ContentSwiftName: Test_Core {

func testExisting() throws {
let nameMaker = makeTranslator(featureFlags: []).contentSwiftName
let cases: [(String, String)] = [
("application/json", "json"),
("application/x-www-form-urlencoded", "binary"),
("multipart/form-data", "binary"),
("text/plain", "text"),
("*/*", "binary"),
("application/xml", "binary"),
("application/octet-stream", "binary"),
("application/myformat+json", "json"),
("foo/bar", "binary"),
]
try _testIdentifiers(cases: cases, nameMaker: nameMaker)
}

func testProposed() throws {
let nameMaker = makeTranslator(featureFlags: [.multipleContentTypes]).contentSwiftName
let cases: [(String, String)] = [
("application/json", "unsupported"),
("application/x-www-form-urlencoded", "unsupported"),
("multipart/form-data", "unsupported"),
("text/plain", "unsupported"),
("*/*", "unsupported"),
("application/xml", "unsupported"),
("application/octet-stream", "unsupported"),
("application/myformat+json", "unsupported"),
("foo/bar", "unsupported"),
]
try _testIdentifiers(cases: cases, nameMaker: nameMaker)
}

func _testIdentifiers(cases: [(String, String)], nameMaker: (ContentType) -> String) throws {
for item in cases {
let contentType = try XCTUnwrap(ContentType(item.0))
XCTAssertEqual(nameMaker(contentType), item.1, "Case \(item.0) failed")
}
}
}

0 comments on commit b6de8a1

Please sign in to comment.