Skip to content

CharacterSet : Codable implementation #1127

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

Merged
merged 7 commits into from
Jul 27, 2017
Merged

Conversation

bubski
Copy link
Contributor

@bubski bubski commented Jul 22, 2017

Continuation of #1108
This PR mirrors some changes from swiftlang/swift#9715


Added conformances + unit tests for

  • CharacterSet
    CharacterSet : Equatable was not working correctly in some cases and was fixed to make Codable unit tests for CharacterSet work.

Not included in this PR, because of some problems that need to be solved

  • Calendar
  • DateComponents
  • Measurement
  • TimeZone

Already implemented

  • PersonNameComponents
  • UUID
  • URL
  • NSRange
  • Locale
  • IndexSet
  • IndexPath
  • AffineTransform
  • Decimal
  • DateInterval
  • CGFloat (unit tested indirectly)

@ianpartridge ianpartridge requested a review from itaiferber July 25, 2017 11:18
Copy link
Contributor

@itaiferber itaiferber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks reasonable overall, but I think we can simplify the tests a bit.

@@ -469,7 +469,7 @@ public struct CharacterSet : ReferenceConvertible, Equatable, Hashable, SetAlgeb

/// Returns true if the two `CharacterSet`s are equal.
public static func ==(lhs : CharacterSet, rhs: CharacterSet) -> Bool {
return lhs._wrapped.isEqual(rhs._bridgeToObjectiveC()) // TODO: mlehew - as NSCharacterSet
return lhs._mapUnmanaged { l in rhs._mapUnmanaged { r in l.isEqual(r) } }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What changed here? Is there an effective difference? A comment would be helpful.

Copy link
Contributor Author

@bubski bubski Jul 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a comment.

The problem was rhs._bridgeToObjectiveC() would always return an invalid (empty) CharacterSet.
._mapUnmanaged behaved correctly.

Now that I think about it, it can actually be changed to

return lhs._mapUnmanaged { $0.isEqual(rhs) }

PS
I actually fixed ._bridgeToObjectiveC() in this PR too, so
lhs._wrapped.isEqual(rhs._bridgeToObjectiveC()) would start working correctly,
but I think lhs._mapUnmanaged { $0.isEqual(rhs) } follows better the pattern seen in other methods of CharacterSet, like

    public func isSuperset(of other: CharacterSet) -> Bool {
        return _mapUnmanaged { $0.isSuperset(of: other) }
    }

Does that make sense @itaiferber ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, reasonable, and makes sense. Comments both in here and in _bridgeToObjectiveC() explaining what makes this work (vs. doesn't) would be nice. Thank you! 🙂


private func assert(equal: Bool,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If keeping the Box is helpful/necessary, then the following comment applies: All of these new asserts seem a bit out of place. Is it not sufficient to make the Box Equatable and perform these checks in ==? (The unit tests can then continue using XCTAssertEqual.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@itaiferber These are very good suggestions, thanks. I'll revisit this. And update this PR.

I wanted to make sure various different equality check combinations are covered, because I was running into inconsistent results in unexpected scenarios.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@itaiferber I've done the tests refactor. Much cleaner 👍
Please let me know if it looks ok to you now.

@@ -17,7 +15,93 @@ import SwiftFoundation
import SwiftXCTest
#endif

private struct Box {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this Box necessary? This doesn't seem to be significantly less work than just replicating some tests:

for (lhs, rhs) in pairs {
    XCTAssertEqual(NSCharacterSet(charactersIn: lhs), NSCharacterSet(charactersIn: rhs))
    XCTAssertEqual(CharacterSet(charactersIn: lhs), CharacterSet(charactersIn: rhs))
}

@@ -486,7 +486,10 @@ extension CharacterSet : _ObjectTypeBridgeable {

@_semantics("convertToObjectiveC")
public func _bridgeToObjectiveC() -> NSCharacterSet {
return _wrapped
switch _wrapped.__wrapped {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@phausler I'd like to run this against you and ask for advice.

I'm not sure if this solutionis ok.

Perhaps it makes more sense to keep return _wrapped here, and add

override var _cfObject: CFType {
    return _mapUnmanaged { unsafeBitCast($0, to: CFType.self) }
}

to _SwiftNSCharacterSet

The problem I'm trying to solve is that we return _wrapped here, which is _SwiftNSCharacterSet.
Somewhere later, we access ._cfObject in this object, which does unsafeBitCast(self, to: CFType.self).
But this doesn't work correctly, because _SwiftNSCharacterSet has different structure than CFCharacterSet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@parkera ^^^

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bubski The new solution sounds reasonable to me. Have you tested locally to confirm the expected behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@itaiferber yes, I have 👌 seems to be working ok.

But I'm not that comfortable with the way copy-on-write is set up yet, so would like someone to double-check this please.

Copy link
Contributor

@itaiferber itaiferber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look good to me!

@itaiferber
Copy link
Contributor

@swift-ci Please test

@ianpartridge
Copy link
Contributor

@swift-ci please test and merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants