Skip to content

Commit

Permalink
Improve handling of Optional referenced types.
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonbloom committed Apr 1, 2024
1 parent d01e68a commit 1ed3e18
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extension FileTranslator {
let typealiasDescription = TypealiasDescription(
accessModifier: config.access,
name: typeName.shortSwiftName,
existingType: .init(existingTypeUsage.withOptional(false))
existingType: .init(existingTypeUsage)
)
let typealiasComment: Comment? = typeName.docCommentWithUserDescription(userDescription)
return .commentable(typealiasComment, .typealias(typealiasDescription))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ extension TypesFileTranslator {
let decl = try translateSchema(
typeName: typeName,
schema: parameter.schema,
overrides: .init(isOptional: !parameter.required, userDescription: parameter.parameter.description)
overrides: .init(userDescription: parameter.parameter.description)
)
return decl
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ extension TypesFileTranslator {
let decl = try translateSchema(
typeName: typeName,
schema: header.schema,
overrides: .init(isOptional: header.isOptional, userDescription: header.header.description)
overrides: .init(userDescription: header.header.description)
)
return decl
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ struct TypeAssigner {
swiftComponent: asSwiftSafeName(originalName) + suffix,
jsonComponent: jsonReferenceComponentOverride ?? originalName
)
.asUsage.withOptional(try typeMatcher.isOptional(schema, components: components))
.asUsage.withOptional(try typeMatcher.isOptionalRoot(schema, components: components))
}

/// Returns a type name for a reusable component.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct TypeMatcher {
},
genericArrayHandler: { TypeName.arrayContainer.asUsage }
)?
.withOptional(isOptional(schema, components: components))
.withOptional(isOptionalRoot(schema, components: components))
}

/// Returns a Boolean value that indicates whether the schema
Expand Down Expand Up @@ -331,6 +331,25 @@ struct TypeMatcher {
return result
}

/// Returns a Boolean value indicating whether the schema is optional at the root of any references.
/// - Parameters:
/// - schema: The reference to check.
/// - components: The OpenAPI components for looking up references.
/// - Throws: An error if there's an issue while checking the schema.
/// - Returns: `true` if the schema is an optional root, `false` otherwise.
func isOptionalRoot(_ schema: JSONSchema, components: OpenAPI.Components) throws -> Bool {
let directlyOptional = schema.nullable || !schema.required
switch schema.value {
case .null(_):
return true
case .reference(let ref, _):
let indirectlyOptional = try isOptional(ref, components: components)
return directlyOptional && !indirectlyOptional
default:
return directlyOptional
}
}

// MARK: - Private

/// Returns the type name of a built-in type that matches the specified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ final class SnippetBasedReferenceTests: XCTestCase {
""",
"""
public enum Schemas {
public typealias Null = OpenAPIRuntime.OpenAPIValueContainer
public typealias Null = OpenAPIRuntime.OpenAPIValueContainer?
public typealias NullArray = [Components.Schemas.Null]
}
""")
Expand Down Expand Up @@ -520,17 +520,17 @@ final class SnippetBasedReferenceTests: XCTestCase {
"""
public enum Schemas {
public typealias MyRequiredString = Swift.String
public typealias MyNullableString = Swift.String
public typealias MyNullableString = Swift.String?
public struct MyObject: Codable, Hashable, Sendable {
public var id: Swift.Int64
public var alias: Swift.String?
public var requiredString: Components.Schemas.MyRequiredString
public var nullableString: Components.Schemas.MyNullableString?
public var nullableString: Components.Schemas.MyNullableString
public init(
id: Swift.Int64,
alias: Swift.String? = nil,
requiredString: Components.Schemas.MyRequiredString,
nullableString: Components.Schemas.MyNullableString? = nil
nullableString: Components.Schemas.MyNullableString
) {
self.id = id
self.alias = alias
Expand Down

0 comments on commit 1ed3e18

Please sign in to comment.