Skip to content

Commit 94f9f20

Browse files
authored
Merge pull request #429 from mattpolzin/feature/425/oas3-2-0
2 parents cc44467 + 5ab7759 commit 94f9f20

File tree

14 files changed

+518
-30
lines changed

14 files changed

+518
-30
lines changed

.github/workflows/tests.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,6 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
image:
16-
- swift:5.8-focal
17-
- swift:5.8-jammy
18-
- swift:5.9-focal
19-
- swift:5.9-jammy
2016
- swift:5.10-focal
2117
- swift:5.10-jammy
2218
- swift:6.0-focal
@@ -25,6 +21,8 @@ jobs:
2521
- swift:6.1-focal
2622
- swift:6.1-jammy
2723
- swift:6.1-noble
24+
- swift:6.2-jammy
25+
- swift:6.2-noble
2826
- swiftlang/swift:nightly-focal
2927
- swiftlang/swift:nightly-jammy
3028
container: ${{ matrix.image }}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![sswg:sandbox|94x20](https://img.shields.io/badge/sswg-sandbox-lightgrey.svg)](https://github.com/swift-server/sswg/blob/master/process/incubation.md#sandbox-level) [![Swift 5.8+](http://img.shields.io/badge/Swift-5.8+-blue.svg)](https://swift.org)
1+
[![sswg:sandbox|94x20](https://img.shields.io/badge/sswg-sandbox-lightgrey.svg)](https://github.com/swift-server/sswg/blob/master/process/incubation.md#sandbox-level) [![Swift 5.10+](http://img.shields.io/badge/Swift-5.10+-blue.svg)](https://swift.org)
22

33
[![MIT license](http://img.shields.io/badge/license-MIT-lightgrey.svg)](http://opensource.org/licenses/MIT) ![Tests](https://github.com/mattpolzin/OpenAPIKit/workflows/Tests/badge.svg)
44

Sources/OpenAPIKit/Document/Document.swift

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -430,23 +430,28 @@ extension OpenAPI.Document {
430430
/// specification releases a new patch version, OpenAPIKit will see a patch version release
431431
/// explicitly supports decoding documents of that new patch version before said version will
432432
/// succesfully decode as the `v3_1_x` case.
433-
public enum Version: RawRepresentable, Equatable, Codable, Sendable {
433+
public enum Version: RawRepresentable, Equatable, Comparable, Codable, Sendable {
434434
case v3_1_0
435435
case v3_1_1
436436
case v3_1_2
437437
case v3_1_x(x: Int)
438438

439+
case v3_2_0
440+
case v3_2_x(x: Int)
441+
439442
public init?(rawValue: String) {
440443
switch rawValue {
441444
case "3.1.0": self = .v3_1_0
442445
case "3.1.1": self = .v3_1_1
443446
case "3.1.2": self = .v3_1_2
447+
case "3.2.0": self = .v3_2_0
444448
default:
445449
let components = rawValue.split(separator: ".")
446450
guard components.count == 3 else {
447451
return nil
448452
}
449-
guard components[0] == "3", components[1] == "1" else {
453+
let minorVersion = components[1]
454+
guard components[0] == "3", (minorVersion == "1" || minorVersion == "2") else {
450455
return nil
451456
}
452457
guard let patchVersion = Int(components[2], radix: 10) else {
@@ -455,10 +460,17 @@ extension OpenAPI.Document {
455460
// to support newer versions released in the future without a breaking
456461
// change to the enumeration, bump the upper limit here to e.g. 2 or 3
457462
// or 6:
458-
guard patchVersion > 1 && patchVersion <= 2 else {
459-
return nil
463+
if minorVersion == "2" {
464+
guard patchVersion > 0 && patchVersion <= 0 else {
465+
return nil
466+
}
467+
self = .v3_2_x(x: patchVersion)
468+
} else {
469+
guard patchVersion > 2 && patchVersion <= 2 else {
470+
return nil
471+
}
472+
self = .v3_1_x(x: patchVersion)
460473
}
461-
self = .v3_1_x(x: patchVersion)
462474
}
463475
}
464476

@@ -468,6 +480,73 @@ extension OpenAPI.Document {
468480
case .v3_1_1: return "3.1.1"
469481
case .v3_1_2: return "3.1.2"
470482
case .v3_1_x(x: let x): return "3.1.\(x)"
483+
484+
case .v3_2_0: return "3.2.0"
485+
case .v3_2_x(x: let x): return "3.2.\(x)"
486+
}
487+
}
488+
489+
public static func < (lhs: Self, rhs: Self) -> Bool {
490+
switch lhs {
491+
case .v3_1_0:
492+
switch rhs {
493+
case .v3_1_0: false
494+
case .v3_1_1: true
495+
case .v3_1_2: true
496+
case .v3_1_x(x: let x): 0 < x
497+
case .v3_2_0: true
498+
case .v3_2_x(x: _): true
499+
}
500+
501+
case .v3_1_1:
502+
switch rhs {
503+
case .v3_1_0: false
504+
case .v3_1_1: false
505+
case .v3_1_2: true
506+
case .v3_1_x(x: let y): 1 < y
507+
case .v3_2_0: true
508+
case .v3_2_x(x: _): true
509+
}
510+
511+
case .v3_1_2:
512+
switch rhs {
513+
case .v3_1_0: false
514+
case .v3_1_1: false
515+
case .v3_1_2: false
516+
case .v3_1_x(x: let y): 2 < y
517+
case .v3_2_0: true
518+
case .v3_2_x(x: _): true
519+
}
520+
521+
case .v3_1_x(x: let x):
522+
switch rhs {
523+
case .v3_1_0: x < 0
524+
case .v3_1_1: x < 1
525+
case .v3_1_2: x < 2
526+
case .v3_1_x(x: let y): x < y
527+
case .v3_2_0: true
528+
case .v3_2_x(x: _): true
529+
}
530+
531+
case .v3_2_0:
532+
switch rhs {
533+
case .v3_1_0: false
534+
case .v3_1_1: false
535+
case .v3_1_2: false
536+
case .v3_1_x(x: _): false
537+
case .v3_2_0: false
538+
case .v3_2_x(x: let y): 0 < y
539+
}
540+
541+
case .v3_2_x(x: let x):
542+
switch rhs {
543+
case .v3_1_0: false
544+
case .v3_1_1: false
545+
case .v3_1_2: false
546+
case .v3_1_x(x: _): false
547+
case .v3_2_0: x < 0
548+
case .v3_2_x(x: let y): x < y
549+
}
471550
}
472551
}
473552
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
public protocol Condition: Equatable, Sendable {
2+
/// Given an entire OpenAPI Document, determine the applicability of the
3+
/// condition.
4+
func applies(to: OpenAPI.Document) -> Bool
5+
}
6+
7+
public protocol HasConditionalWarnings {
8+
/// Warnings that only apply if the paired condition is met.
9+
///
10+
/// Among other things, this allows OpenAPIKit to generate a warning in
11+
/// some nested type that only applies if the OpenAPI Standards version of
12+
/// the document is less than a certain version.
13+
var conditionalWarnings: [(any Condition, OpenAPI.Warning)] { get }
14+
}
15+
16+
extension HasConditionalWarnings {
17+
public func applicableConditionalWarnings(for subject: OpenAPI.Document) -> [OpenAPI.Warning] {
18+
conditionalWarnings.compactMap { (condition, warning) in
19+
guard condition.applies(to: subject) else { return nil }
20+
21+
return warning
22+
}
23+
}
24+
}
25+
26+
internal struct DocumentVersionCondition: Sendable, Condition {
27+
enum Comparator: Sendable {
28+
case lessThan
29+
case equal
30+
case greaterThan
31+
}
32+
33+
let version: OpenAPI.Document.Version
34+
let comparator: Comparator
35+
36+
func applies(to document: OpenAPI.Document) -> Bool {
37+
switch comparator {
38+
case .lessThan: document.openAPIVersion < version
39+
40+
case .equal: document.openAPIVersion == version
41+
42+
case .greaterThan: document.openAPIVersion > version
43+
}
44+
}
45+
}
46+
47+
internal extension OpenAPI.Document {
48+
struct ConditionalWarnings {
49+
static func version(lessThan version: OpenAPI.Document.Version, doesNotSupport subject: String) -> (any Condition, OpenAPI.Warning) {
50+
let warning = OpenAPI.Warning.message("\(subject) is only supported for OpenAPI document versions \(version.rawValue) and later")
51+
52+
return (DocumentVersionCondition(version: version, comparator: .lessThan), warning)
53+
}
54+
}
55+
}

Sources/OpenAPIKit/Schema Object/JSONSchemaContext.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ extension JSONSchema.CoreContext: Decodable {
10421042
.underlyingError(
10431043
GenericError(
10441044
subjectName: "OpenAPI Schema",
1045-
details: "Found 'nullable' property. This property is not supported by OpenAPI v3.1.x. OpenAPIKit has translated it into 'type: [\"null\", ...]'.",
1045+
details: "Found 'nullable' property. This property is not supported by OpenAPI v3.1.x. OpenAPIKit has translated it into 'type: [\"null\", ...]'",
10461046
codingPath: container.codingPath
10471047
)
10481048
)

0 commit comments

Comments
 (0)