Skip to content

Commit 577bafd

Browse files
authored
Skip inferred properties (#381)
### Motivation Fixes #379. Context: If you define an object schema as follows: ```yaml Foo: type: object properties: a: type: string required: - b ``` OpenAPIKit will parse it as having two properties: `a` of type `string` and `b` being a fragment, with `a` optional and `b` required. Unfortunately, often property names appear _only_ in the `required` list as a result of a typo, leading to non-compiling code and a difficult debugging story. It comes down to the fact that Swift OpenAPI Generator never officially supported defining properties this way, and continues not to. If adopters want to do this intentionally, they should do this: ```yaml Foo: type: object properties: a: type: string b: {} required: - b ``` ### Modifications This PR tightens the rules around inferred properties: 1. Inferred properties are skipped, so the result of the first example will only have the property `a` generated, and the second example both `a` and `b`. 2. The generator emits a warning diagnostic when encountering an inferred property, which should help adopters who made a typo catch it much earlier in the process. 3. Bumps OpenAPIKit to 3.1.0, as the `inferred` property was added just yesterday. ### Result Less likely typos and mismatch between `properties` and `required`, and a diagnostic to help debug this case. ### Test Plan Added a snippet test.
1 parent 82323ce commit 577bafd

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ let package = Package(
5555
.package(url: "https://github.com/apple/swift-algorithms", from: "1.0.0"),
5656

5757
// Read OpenAPI documents
58-
.package(url: "https://github.com/mattpolzin/OpenAPIKit.git", from: "3.0.1"),
58+
.package(url: "https://github.com/mattpolzin/OpenAPIKit.git", from: "3.1.0"),
5959
.package(url: "https://github.com/jpsim/Yams.git", "4.0.0"..<"6.0.0"),
6060

6161
// CLI Tool

Sources/_OpenAPIGeneratorCore/Translator/CommonTranslations/translateObjectStruct.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ extension FileTranslator {
3838

3939
let foundIn = "\(typeName.description)/\(key)"
4040

41+
// Properties that are only defined in the `required` list but don't
42+
// have a proper definition in the `properties` map are skipped, as they
43+
// often imply a typo or a mistake in the document. So emit a diagnostic as well.
44+
guard !value.inferred else {
45+
diagnostics.emit(
46+
.warning(
47+
message:
48+
"A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property.",
49+
context: ["foundIn": foundIn]
50+
)
51+
)
52+
return false
53+
}
54+
4155
// We need to catch a special case here:
4256
// type: string + format: binary.
4357
// It means binary data (unlike format: byte, which means base64

Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,38 @@ final class SnippetBasedReferenceTests: XCTestCase {
156156
)
157157
}
158158

159+
func testComponentsSchemasObjectWithInferredProperty() throws {
160+
try self.assertSchemasTranslation(
161+
ignoredDiagnosticMessages: [
162+
"A property name only appears in the required list, but not in the properties map - this is likely a typo; skipping this property."
163+
],
164+
"""
165+
schemas:
166+
MyObj:
167+
type: object
168+
properties:
169+
fooRequired:
170+
type: string
171+
required:
172+
- fooRequired
173+
- fooInferred
174+
""",
175+
"""
176+
public enum Schemas {
177+
public struct MyObj: Codable, Hashable, Sendable {
178+
public var fooRequired: Swift.String
179+
public init(fooRequired: Swift.String) {
180+
self.fooRequired = fooRequired
181+
}
182+
public enum CodingKeys: String, CodingKey {
183+
case fooRequired
184+
}
185+
}
186+
}
187+
"""
188+
)
189+
}
190+
159191
func testComponentsObjectNoAdditionalProperties() throws {
160192
try self.assertSchemasTranslation(
161193
"""

0 commit comments

Comments
 (0)