Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Refactor] Introduce TranslatorContext (2/2) #640

Merged
merged 4 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ extension TypesFileTranslator {
parent: typeName
)
let associatedDeclarations: [Declaration]
if TypeMatcher.isInlinable(schema) {
if typeMatcher.isInlinable(schema) {
associatedDeclarations = try translateSchema(
typeName: propertyType.typeName,
schema: schema,
Expand All @@ -81,7 +81,7 @@ extension TypesFileTranslator {
context: context
)
var referenceStack = ReferenceStack.empty
let isKeyValuePairSchema = try TypeMatcher.isKeyValuePair(
let isKeyValuePairSchema = try typeMatcher.isKeyValuePair(
schema,
referenceStack: &referenceStack,
components: components
Expand Down Expand Up @@ -173,7 +173,7 @@ extension TypesFileTranslator {
parent: typeName
)
let associatedDeclarations: [Declaration]
if TypeMatcher.isInlinable(schema) {
if typeMatcher.isInlinable(schema) {
associatedDeclarations = try translateSchema(
typeName: childType.typeName,
schema: schema,
Expand All @@ -183,7 +183,7 @@ extension TypesFileTranslator {
associatedDeclarations = []
}
var referenceStack = ReferenceStack.empty
let isKeyValuePair = try TypeMatcher.isKeyValuePair(
let isKeyValuePair = try typeMatcher.isKeyValuePair(
schema,
referenceStack: &referenceStack,
components: components
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ extension TypesFileTranslator {
parent: typeName
)
let associatedDeclarations: [Declaration]
if TypeMatcher.isInlinable(value) {
if typeMatcher.isInlinable(value) {
associatedDeclarations = try translateSchema(
typeName: propertyType.typeName,
schema: value,
Expand Down Expand Up @@ -153,7 +153,7 @@ extension TypesFileTranslator {
components: components,
inParent: parent
)
if TypeMatcher.isInlinable(schema) {
if typeMatcher.isInlinable(schema) {
associatedDeclarations = try translateSchema(
typeName: valueTypeUsage.typeName,
schema: schema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ extension MultipartSchemaTypedContent {
}
}

extension SchemaContent {
extension TypeMatcher {
/// Returns a Boolean value whether the schema is a multipart content type and is referenceable.
var isReferenceableMultipart: Bool {
guard contentType.isMultipart else { return false }
let ref = TypeMatcher.multipartElementTypeReferenceIfReferenceable(schema: schema, encoding: encoding)
func isReferenceableMultipart(_ content: SchemaContent) -> Bool {
guard content.contentType.isMultipart else { return false }
let ref = multipartElementTypeReferenceIfReferenceable(schema: content.schema, encoding: content.encoding)
return ref == nil
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ extension TypesFileTranslator {
inParent: typeName.appending(swiftComponent: nil, jsonComponent: "content")
)
let associatedDeclarations: [Declaration]
if TypeMatcher.isInlinable(schema) {
if typeMatcher.isInlinable(schema) {
associatedDeclarations = try translateSchema(
typeName: bodyTypeUsage.typeName,
schema: schema,
Expand Down Expand Up @@ -117,7 +117,7 @@ extension TypesFileTranslator {
schema: JSONSchema
) throws -> [Declaration] {
let associatedDeclarations: [Declaration]
if TypeMatcher.isInlinable(schema) {
if typeMatcher.isInlinable(schema) {
associatedDeclarations = try translateSchema(typeName: typeName, schema: schema, overrides: .none)
} else {
associatedDeclarations = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,14 @@ extension TypedParameter {
/// The location of the parameter in the HTTP request.
var location: OpenAPI.Parameter.Context.Location { parameter.location }

/// A schema to be inlined.
///
/// - Returns: Nil when schema is referenceable.
var inlineableSchema: JSONSchema? { schema.inlineableSchema }
}

extension UnresolvedSchema {

/// A schema to be inlined.
///
/// - Returns: Nil when schema is referenceable.
var inlineableSchema: JSONSchema? {
switch self {
switch schema {
case .a: return nil
case let .b(schema):
if TypeMatcher.isInlinable(schema) { return schema }
if TypeMatcher(context: context).isInlinable(schema) { return schema }
return nil
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ extension TypesFileTranslator {
let contentTypeName = typeName.appending(jsonComponent: "content")
let contents = requestBody.contents
for content in contents {
if TypeMatcher.isInlinable(content.content.schema) || content.content.isReferenceableMultipart {
if typeMatcher.isInlinable(content.content.schema) || typeMatcher.isReferenceableMultipart(content.content)
{
let inlineTypeDecls = try translateRequestBodyContentInTypes(content)
bodyMembers.append(contentsOf: inlineTypeDecls)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ extension TypesFileTranslator {
let associatedType = typedContent.resolvedTypeUsage
let content = typedContent.content
let schema = content.schema
if TypeMatcher.isInlinable(schema) || content.isReferenceableMultipart {
if typeMatcher.isInlinable(schema) || typeMatcher.isReferenceableMultipart(content) {
let decls: [Declaration]
if contentType.isMultipart {
decls = try translateMultipartBody(typedContent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ extension TypesFileTranslator {
let schema = header.schema
let typeUsage = header.typeUsage
let associatedDeclarations: [Declaration]
if TypeMatcher.isInlinable(schema) {
if typeMatcher.isInlinable(schema) {
associatedDeclarations = try translateSchema(typeName: typeUsage.typeName, schema: schema, overrides: .none)
} else {
associatedDeclarations = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ struct TypeAssigner {
inParent parent: TypeName
) throws -> TypeUsage {
let multipartBodyElementTypeName: TypeName
if let ref = TypeMatcher.multipartElementTypeReferenceIfReferenceable(schema: schema, encoding: encoding) {
if let ref = TypeMatcher(context: context)
.multipartElementTypeReferenceIfReferenceable(schema: schema, encoding: encoding)
{
multipartBodyElementTypeName = try typeName(for: ref)
} else {
let swiftSafeName = context.asSwiftSafeName(hint)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct TypeMatcher {
func tryMatchBuiltinType(for schema: JSONSchema.Schema) -> TypeUsage? {
Self._tryMatchRecursive(
for: schema,
test: { schema in Self._tryMatchBuiltinNonRecursive(for: schema) },
test: { schema in _tryMatchBuiltinNonRecursive(for: schema) },
matchedArrayHandler: { elementType, nullableItems in
nullableItems ? elementType.asOptional.asArray : elementType.asArray
},
Expand All @@ -68,7 +68,7 @@ struct TypeMatcher {
try Self._tryMatchRecursive(
for: schema.value,
test: { (schema) -> TypeUsage? in
if let builtinType = Self._tryMatchBuiltinNonRecursive(for: schema) { return builtinType }
if let builtinType = _tryMatchBuiltinNonRecursive(for: schema) { return builtinType }
guard case let .reference(ref, _) = schema else { return nil }
return try TypeAssigner(context: context).typeName(for: ref).asUsage
czechboy0 marked this conversation as resolved.
Show resolved Hide resolved
},
Expand All @@ -88,9 +88,9 @@ struct TypeMatcher {
/// - A reference
/// - Parameter schema: The schema to match a referenceable type for.
/// - Returns: `true` if the schema is referenceable; `false` otherwise.
static func isReferenceable(_ schema: JSONSchema) -> Bool {
func isReferenceable(_ schema: JSONSchema) -> Bool {
// This logic should be kept in sync with `tryMatchReferenceableType`.
_tryMatchRecursive(
Self._tryMatchRecursive(
for: schema.value,
test: { schema in
if _tryMatchBuiltinNonRecursive(for: schema) != nil { return true }
Expand All @@ -110,7 +110,7 @@ struct TypeMatcher {
/// - A reference
/// - Parameter schema: The schema to match a referenceable type for.
/// - Returns: `true` if the schema is referenceable; `false` otherwise.
static func isReferenceable(_ schema: UnresolvedSchema?) -> Bool {
func isReferenceable(_ schema: UnresolvedSchema?) -> Bool {
guard let schema else {
// fragment type is referenceable
return true
Expand All @@ -132,7 +132,7 @@ struct TypeMatcher {
/// referenceable.
/// - Parameter schema: The schema to match a referenceable type for.
/// - Returns: `true` if the schema is inlinable; `false` otherwise.
static func isInlinable(_ schema: JSONSchema) -> Bool { !isReferenceable(schema) }
func isInlinable(_ schema: JSONSchema) -> Bool { !isReferenceable(schema) }

/// Returns a Boolean value that indicates whether the schema
/// needs to be defined inline.
Expand All @@ -143,14 +143,14 @@ struct TypeMatcher {
/// referenceable.
/// - Parameter schema: The schema to match a referenceable type for.
/// - Returns: `true` if the schema is inlinable; `false` otherwise.
static func isInlinable(_ schema: UnresolvedSchema?) -> Bool { !isReferenceable(schema) }
func isInlinable(_ schema: UnresolvedSchema?) -> Bool { !isReferenceable(schema) }

/// Return a reference to a multipart element type if the provided schema is referenceable.
/// - Parameters:
/// - schema: The schema to try to reference.
/// - encoding: The associated encoding.
/// - Returns: A reference if the schema is referenceable, nil otherwise.
static func multipartElementTypeReferenceIfReferenceable(
func multipartElementTypeReferenceIfReferenceable(
schema: UnresolvedSchema?,
encoding: OrderedDictionary<String, OpenAPI.Content.Encoding>?
) -> OpenAPI.Reference<JSONSchema>? {
Expand All @@ -174,11 +174,9 @@ struct TypeMatcher {
/// - components: The reusable components from the OpenAPI document.
/// - Throws: An error if there's an issue while checking the schema.
/// - Returns: `true` if the schema is a key-value pair; `false` otherwise.
static func isKeyValuePair(
_ schema: JSONSchema,
referenceStack: inout ReferenceStack,
components: OpenAPI.Components
) throws -> Bool {
func isKeyValuePair(_ schema: JSONSchema, referenceStack: inout ReferenceStack, components: OpenAPI.Components)
throws -> Bool
{
switch schema.value {
case .object, .fragment: return true
case .null, .boolean, .number, .integer, .string, .array, .not: return false
Expand Down Expand Up @@ -222,7 +220,7 @@ struct TypeMatcher {
/// - components: The reusable components from the OpenAPI document.
/// - Throws: An error if there's an issue while checking the schema.
/// - Returns: `true` if the schema is a key-value pair; `false` otherwise.
static func isKeyValuePair(
func isKeyValuePair(
_ schema: UnresolvedSchema?,
referenceStack: inout ReferenceStack,
components: OpenAPI.Components
Expand Down Expand Up @@ -285,7 +283,7 @@ struct TypeMatcher {
/// - Parameter schema: The schema to match a referenceable type for.
/// - Returns: A type usage for the schema if the schema is built-in.
/// Otherwise, returns nil.
private static func _tryMatchBuiltinNonRecursive(for schema: JSONSchema.Schema) -> TypeUsage? {
private func _tryMatchBuiltinNonRecursive(for schema: JSONSchema.Schema) -> TypeUsage? {
let typeName: TypeName
switch schema {
case .boolean(_): typeName = .swift("Bool")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ final class Test_TypeMatcher: Test_Core {
.fullyQualifiedSwiftName,
name
)
XCTAssertTrue(TypeMatcher.isReferenceable(schema))
XCTAssertFalse(TypeMatcher.isInlinable(schema))
XCTAssertTrue(typeMatcher.isReferenceable(schema))
XCTAssertFalse(typeMatcher.isInlinable(schema))
}
}

Expand All @@ -145,8 +145,8 @@ final class Test_TypeMatcher: Test_Core {
typeMatcher.tryMatchBuiltinType(for: schema.value),
"Type is expected to not match a builtin type: \(schema)"
)
XCTAssertFalse(TypeMatcher.isReferenceable(schema), "Expected schema not to be referenceable: \(schema)")
XCTAssertTrue(TypeMatcher.isInlinable(schema), "Expected schema to be inlinable: \(schema)")
XCTAssertFalse(typeMatcher.isReferenceable(schema), "Expected schema not to be referenceable: \(schema)")
XCTAssertTrue(typeMatcher.isInlinable(schema), "Expected schema to be inlinable: \(schema)")
}
}

Expand Down Expand Up @@ -175,7 +175,7 @@ final class Test_TypeMatcher: Test_Core {
for schema in Self.keyValuePairTypes {
var referenceStack = ReferenceStack.empty
XCTAssertTrue(
try TypeMatcher.isKeyValuePair(schema, referenceStack: &referenceStack, components: components),
try typeMatcher.isKeyValuePair(schema, referenceStack: &referenceStack, components: components),
"Type is expected to be a key-value pair schema: \(schema)"
)
}
Expand Down Expand Up @@ -249,13 +249,12 @@ final class Test_TypeMatcher: Test_Core {
]
func testMultipartElementTypeReferenceIfReferenceableTypes() throws {
for (schema, encoding, name) in Self.multipartElementTypeReferenceIfReferenceableTypes {
let actualName = TypeMatcher.multipartElementTypeReferenceIfReferenceable(
let actualName = typeMatcher.multipartElementTypeReferenceIfReferenceable(
schema: schema,
encoding: encoding
)?
.name
XCTAssertEqual(actualName, name)
}
}

}