-
Notifications
You must be signed in to change notification settings - Fork 200
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
fix(api): add collection type casting in swift 5.7 #3602
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor refactoring comment, let me know if you need another approval if adopting it
#if swift(<5.8) | ||
if let errors = errors.cast(to: AppSyncRealTimeRequest.Error.self) { | ||
let hasAuthorizationError = errors.contains(where: { $0 == .unauthorized}) | ||
return APIError.operationError( | ||
errorDescription(hasAuthorizationError), | ||
"", | ||
errors.first | ||
) | ||
} else if let errors = errors.cast(to: GraphQLError.self) { | ||
let hasAuthorizationError = errors.map(\.extensions) | ||
.compactMap { $0.flatMap { $0["errorType"]?.stringValue } } | ||
.contains(where: { AppSyncErrorType($0) == .unauthorized }) | ||
return APIError.operationError( | ||
errorDescription(hasAuthorizationError), | ||
"", | ||
GraphQLResponseError<R>.error(errors) | ||
) | ||
} else { | ||
return APIError.operationError( | ||
errorDescription(), | ||
"", | ||
errors.first | ||
) | ||
} | ||
#else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like you can probably reduce this once more
let hasAuthorizationError: Bool
let underlyingError: Error?
#if swift(<5.8)
if let errors = errors.cast(to: AppSyncRealTimeRequest.Error.self) {
hasAuthorizationError = errors.contains(where: { $0 == .unauthorized})
underlyingError = errors.first
} else if let errors = errors.cast(to: GraphQLError.self) {
hasAuthorizationError = errors.map(\.extensions)
.compactMap { $0.flatMap { $0["errorType"]?.stringValue } }
.contains(where: { AppSyncErrorType($0) == .unauthorized })
underlyingError = GraphQLResponseError<R>.error(errors)
} else {
hasAuthorizationError = false
underlyingError = errors.first
}
#else
if let errors = errors as? [AppSyncRealTimeRequest.Error] {
hasAuthorizationError = errors.contains(where: { $0 == .unauthorized})
underlyingError = errors.first
} else if let errors = errors as? [GraphQLError] {
hasAuthorizationError = errors.map(\.extensions)
.compactMap { $0.flatMap { $0["errorType"]?.stringValue } }
.contains(where: { AppSyncErrorType($0) == .unauthorized })
underlyingError = errors.first
} else {
hasAuthorizationError = false
underlyingError = errors.first
}
#endif
return APIError.operationError(
errorDescription(hasAuthorizationError),
"",
underlyingError
)
Or even further, just use cast
everywhere. This would avoid having to duplicate business logic while maintaining the Collection type casting in one place. Once we support 5.8 and up, then we can replace usages of cast
with as
func cast<T>(to type: T.Type) -> [T]? {
#if swift(<5.8)
self.reduce([]) { partialResult, ele in
if let partialResult, let ele = ele as? T {
return partialResult + [ele]
}
return nil
}
#else
return self as? [T]
#endif
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of having the compiler directive in the cast
function instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Including the directive in the cast
func will make unit testing harder. Once we upgrade the Swift tool version to 5.8, removing the code within the annotation will become straightforward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would it make unit testing harder? We don't need to unit-test that we support both 5.7 and 5.8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Chatted with @5d, the CI set up will cause cast
to be unit tested against Swift 5.9 so it won't reach the code path. We'd have to refactor the unit test to test against something like:
func cast<T>(to type: T.Type) -> [T]? {
#if swift(<5.8)
return castSwift5_7() // update unit tests to test this function instead
#else
return self as? [T]
#endif
}
We to upgrade to min 5.8 soon so as Di mentioned it will be easier to remove the code later in the current PR
Issue #
Description
Swift Collection type casting is introduced in
Swift 5.8
. As our library is still supportingSwift 5.7
, adding backward compatibility support for collection casting.General Checklist
Given When Then
inline code documentation and are named accordinglytestThing_condition_expectation()
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.