Skip to content

Commit

Permalink
Support OpenAPI 3.1 in addition to 3.0 (#219)
Browse files Browse the repository at this point in the history
Support OpenAPI 3.1 in addition to 3.0

### Motivation

Fixes #39. We need to start accepting 3.1 documents in addition to 3.0.

It also has useful features, like being able to add descriptions to references.

### Modifications

Migrated the codebase to use the `OpenAPIKit` instead of the `OpenAPIKit30` module, and updated the parser to handle both 3.0 and 3.1, and convert 3.0 to 3.1 documents in memory transparently.

### Result

OpenAPI 3.1 documents are now accepted, instead of rejected. Any 3.1 specific features can be addressed separately, this is the MVP support.

### Test Plan

Updated the file-based reference test to use version 3.1.0, and the parser tests that 3.0.x documents are loaded and converted successfully. So no need to duplicate our reference tests or anything.


Reviewed by: Kyle-Ye, glbrntt

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. 

#219
  • Loading branch information
czechboy0 authored Aug 29, 2023
1 parent 640a58c commit d2dbd0d
Show file tree
Hide file tree
Showing 95 changed files with 180 additions and 173 deletions.
2 changes: 1 addition & 1 deletion IntegrationTest/Sources/openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
openapi: "3.0.3"
openapi: "3.1.0"
info:
title: "GreetingService"
version: "1.0.0"
Expand Down
4 changes: 3 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ let package = Package(
// Read OpenAPI documents
.package(
url: "https://github.com/mattpolzin/OpenAPIKit.git",
exact: "3.0.0-beta.1"
exact: "3.0.0-beta.2"
),
.package(
url: "https://github.com/jpsim/Yams.git",
Expand All @@ -91,7 +91,9 @@ let package = Package(
.target(
name: "_OpenAPIGeneratorCore",
dependencies: [
.product(name: "OpenAPIKit", package: "OpenAPIKit"),
.product(name: "OpenAPIKit30", package: "OpenAPIKit"),
.product(name: "OpenAPIKitCompat", package: "OpenAPIKit"),
.product(name: "Algorithms", package: "swift-algorithms"),
.product(name: "Yams", package: "Yams"),
.product(name: "SwiftSyntax", package: "swift-syntax"),
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ Choose one of the transports listed below, or create your own by adopting the `C

## Requirements and supported features

- Swift 5.8
- OpenAPI 3.0.x
| Generator versions | Supported OpenAPI versions | Minimum Swift version |
| -------- | ------- | ----- |
| `0.1.0` ... `0.1.11` | 3.0 | 5.8 |
| `0.1.12` ... `main` | 3.0, 3.1 | 5.8 |

### Supported platforms and minimum versions

Expand Down
2 changes: 1 addition & 1 deletion Sources/_OpenAPIGeneratorCore/Diagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
import Foundation
import OpenAPIKit30
import OpenAPIKit

/// A message emitted by the generator.
public struct Diagnostic: Error, Codable {
Expand Down
8 changes: 6 additions & 2 deletions Sources/_OpenAPIGeneratorCore/Extensions/OpenAPIKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension Either {

Expand All @@ -20,7 +20,7 @@ extension Either {
/// - Parameter components: The Components section of the OpenAPI document.
func resolve(
in components: OpenAPI.Components
) throws -> B where A == JSONReference<B> {
) throws -> B where A == OpenAPI.Reference<B> {
switch self {
case let .a(a):
return try components.lookup(a)
Expand Down Expand Up @@ -59,6 +59,8 @@ extension JSONSchema.Schema {
return "reference"
case .fragment:
return "fragment"
case .null:
return "null"
}
}

Expand Down Expand Up @@ -89,6 +91,8 @@ extension JSONSchema.Schema {
return nil
case .fragment(let coreContext):
return coreContext.formatString
case .null:
return nil
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/_OpenAPIGeneratorCore/GeneratorPipeline.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit
import Foundation
import Yams

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// An OpenAPIKit document that contains the operations and types for which the generator emits Swift types.
typealias ParsedOpenAPIRepresentation = OpenAPI.Document
40 changes: 24 additions & 16 deletions Sources/_OpenAPIGeneratorCore/Parser/YamsParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
//
//===----------------------------------------------------------------------===//
import Foundation
import OpenAPIKit
import OpenAPIKit30
import OpenAPIKitCompat
import Yams

/// A parser that uses the Yams library to parse the provided
Expand Down Expand Up @@ -44,21 +46,27 @@ struct YamsParser: ParserProtocol {
guard let openAPIVersion = versionedDocument.openapi else {
throw Diagnostic.openAPIMissingVersionError(location: .init(filePath: input.absolutePath.path))
}
switch openAPIVersion {
case "3.0.0", "3.0.1", "3.0.2", "3.0.3":
break
default:
throw Diagnostic.openAPIVersionError(
versionString: "openapi: \(openAPIVersion)",
location: .init(filePath: input.absolutePath.path)
)
}

do {
return try decoder.decode(
OpenAPI.Document.self,
from: input.contents
)
let document: OpenAPIKit.OpenAPI.Document
switch openAPIVersion {
case "3.0.0", "3.0.1", "3.0.2", "3.0.3":
let openAPI30Document = try decoder.decode(
OpenAPIKit30.OpenAPI.Document.self,
from: input.contents
)
document = openAPI30Document.convert(to: .v3_1_0)
case "3.1.0":
document = try decoder.decode(
OpenAPIKit.OpenAPI.Document.self,
from: input.contents
)
default:
throw Diagnostic.openAPIVersionError(
versionString: "openapi: \(openAPIVersion)",
location: .init(filePath: input.absolutePath.path)
)
}
return document
} catch DecodingError.dataCorrupted(let errorContext) {
try checkParsingError(context: errorContext, input: input)
throw DecodingError.dataCorrupted(errorContext)
Expand Down Expand Up @@ -104,7 +112,7 @@ extension Diagnostic {
static func openAPIVersionError(versionString: String, location: Location) -> Diagnostic {
return error(
message:
"Unsupported document version: \(versionString). Please provide a document with OpenAPI versions in the 3.0.x set.",
"Unsupported document version: \(versionString). Please provide a document with OpenAPI versions in the 3.0.x or 3.1.x sets.",
location: location
)
}
Expand All @@ -115,7 +123,7 @@ extension Diagnostic {
static func openAPIMissingVersionError(location: Location) -> Diagnostic {
return error(
message:
"No openapi key found, please provide a valid OpenAPI document with OpenAPI versions in the 3.0.x set.",
"No openapi key found, please provide a valid OpenAPI document with OpenAPI versions in the 3.0.x or 3.1.x sets.",
location: location
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// A translator for the generated client.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension ClientFileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// Describes one of the two options: allOf or anyOf.
enum AllOrAnyOf {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand All @@ -38,7 +38,7 @@ extension FileTranslator {
switch schema {
case let .a(ref):
// reference, wrap that into JSONSchema
unwrappedSchema = .reference(ref)
unwrappedSchema = .reference(ref.jsonReference)
case let .b(schema):
unwrappedSchema = schema
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension Comment {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// Constant values used in generated code, some of which refer to type names
/// in the Runtime library, so they need to be kept in sync.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit
import Foundation

/// A child schema of a oneOf with a discriminator.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// A container of properties that can be defined at multiple levels in
/// the OpenAPI document. If a property is filled in, the value is used instead
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// A structure that contains the information about an OpenAPI object that is
/// required to generate a matching Swift structure.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// Utilities for asking questions about OpenAPI.Content
extension FileTranslator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// A content type of a request, response, and other types.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// A type representing OpenAPI content that contains both a content type
/// and the optional JSON schema.
Expand Down Expand Up @@ -48,4 +48,4 @@ struct TypedSchemaContent {
/// An unresolved OpenAPI schema.
///
/// Can be either a reference or an inline schema.
typealias UnresolvedSchema = Either<JSONReference<JSONSchema>, JSONSchema>
typealias UnresolvedSchema = Either<OpenAPI.Reference<JSONSchema>, JSONSchema>
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

extension FileTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// An object that generates a Swift file for a provided OpenAPI document.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import OpenAPIKit30
import OpenAPIKit

/// A translator that inspects the generator configuration and delegates
/// the code generation logic to the appropriate translator.
Expand Down
Loading

0 comments on commit d2dbd0d

Please sign in to comment.