From d98fbe5772b9eba9d3be092b500d6f035c4b2199 Mon Sep 17 00:00:00 2001 From: Sho Ikeda Date: Wed, 1 Aug 2018 01:53:51 +0900 Subject: [PATCH] [SE-0185] Utilize synthesized Equatable and Hashable conformances https://github.com/apple/swift-evolution/blob/master/proposals/0185-synthesize-equatable-hashable.md --- Sources/Tentacle/Author.swift | 11 -------- Sources/Tentacle/Branch.swift | 24 +---------------- Sources/Tentacle/Commit.swift | 25 +----------------- Sources/Tentacle/Content.swift | 40 +++++------------------------ Sources/Tentacle/File.swift | 11 +------- Sources/Tentacle/FileResponse.swift | 10 -------- Sources/Tentacle/GitHubError.swift | 12 +-------- Sources/Tentacle/Identifiable.swift | 18 +------------ Sources/Tentacle/Organization.swift | 10 -------- Sources/Tentacle/PullRequest.swift | 10 -------- Sources/Tentacle/Request.swift | 14 +++------- Sources/Tentacle/Response.swift | 11 ++------ Sources/Tentacle/Sha.swift | 10 -------- Sources/Tentacle/Tree.swift | 36 +------------------------- Sources/Tentacle/User.swift | 34 ++---------------------- 15 files changed, 19 insertions(+), 257 deletions(-) diff --git a/Sources/Tentacle/Author.swift b/Sources/Tentacle/Author.swift index 52c8414..dbd3207 100644 --- a/Sources/Tentacle/Author.swift +++ b/Sources/Tentacle/Author.swift @@ -19,14 +19,3 @@ public struct Author: ResourceType, Encodable { self.email = email } } - -extension Author: Hashable, Equatable { - public var hashValue: Int { - return name.hashValue ^ email.hashValue - } - - static public func ==(lhs: Author, rhs: Author) -> Bool { - return lhs.name == rhs.name - && lhs.email == rhs.email - } -} diff --git a/Sources/Tentacle/Branch.swift b/Sources/Tentacle/Branch.swift index ee8592f..7a6523c 100644 --- a/Sources/Tentacle/Branch.swift +++ b/Sources/Tentacle/Branch.swift @@ -19,7 +19,7 @@ extension Repository { public struct Branch: ResourceType { - public struct Commit: Decodable { + public struct Commit: ResourceType { public let sha: SHA } @@ -35,25 +35,3 @@ public struct Branch: ResourceType { } } - -extension Branch: Hashable { - public static func ==(lhs: Branch, rhs: Branch) -> Bool { - return lhs.name == rhs.name && lhs.commit == rhs.commit - } - - public var hashValue: Int { - return name.hashValue ^ commit.hashValue - } -} - -extension Branch.Commit: Hashable { - public var hashValue: Int { - return sha.hashValue - } -} - -extension Branch.Commit: Equatable { - public static func ==(lhs: Branch.Commit, rhs: Branch.Commit) -> Bool { - return lhs.sha == rhs.sha - } -} diff --git a/Sources/Tentacle/Commit.swift b/Sources/Tentacle/Commit.swift index 7cd6559..1bb427d 100644 --- a/Sources/Tentacle/Commit.swift +++ b/Sources/Tentacle/Commit.swift @@ -45,7 +45,7 @@ public struct Commit: ResourceType { } } -extension Commit { +extension Commit: Hashable { public var hashValue: Int { return sha.hashValue } @@ -54,26 +54,3 @@ extension Commit { return lhs.sha == rhs.sha } } - -extension Commit.Author { - public var hashValue: Int { - return date.hashValue ^ name.hashValue ^ email.hashValue - } - - public static func ==(lhs: Commit.Author, rhs: Commit.Author) -> Bool { - return lhs.date == rhs.date - && lhs.name == rhs.name - && lhs.email == rhs.email - } -} - -extension Commit.Parent { - public var hashValue: Int { - return sha.hashValue ^ url.hashValue - } - - public static func ==(lhs: Commit.Parent, rhs: Commit.Parent) -> Bool { - return lhs.sha == rhs.sha - && lhs.url == rhs.url - } -} diff --git a/Sources/Tentacle/Content.swift b/Sources/Tentacle/Content.swift index c1d6f5e..a4fb1f1 100644 --- a/Sources/Tentacle/Content.swift +++ b/Sources/Tentacle/Content.swift @@ -30,7 +30,7 @@ extension Repository { /// - directory: a directory when queried directly in a repository (may contain multiple files) public enum Content: ResourceType { /// A file in a repository - public struct File: CustomStringConvertible, Decodable { + public struct File: CustomStringConvertible, ResourceType { public enum ContentTypeName: String, Decodable { case file @@ -45,7 +45,7 @@ public enum Content: ResourceType { /// - directory: a directory in a repository /// - symlink: a symlink in a repository not targeting a file inside the same repository /// - submodule: a submodule in a repository - public enum ContentType: Decodable { + public enum ContentType: Decodable, Equatable { /// A file a in a repository case file(size: Int, downloadURL: URL?) @@ -139,6 +139,10 @@ public enum Content: ResourceType { case content } + // Hashable + public var hashValue: Int { + return name.hashValue + } } case file(File) @@ -182,35 +186,3 @@ extension Content: Hashable { } } } - -extension Content.File.ContentType: Equatable { - public static func ==(lhs: Content.File.ContentType, rhs: Content.File.ContentType) -> Bool { - switch (lhs, rhs) { - case let (.file(size, url), .file(size2, url2)): - return size == size2 && url == url2 - case (.directory, .directory): - return true - case let (.submodule(url), .submodule(url2)): - return url == url2 - case let (.symlink(target, url), .symlink(target2, url2)): - return target == target2 && url == url2 - default: - return false - } - } -} - -extension Content.File: Hashable { - public static func ==(lhs: Content.File, rhs: Content.File) -> Bool { - return lhs.name == rhs.name - && lhs.path == rhs.path - && lhs.sha == rhs.sha - && lhs.content == rhs.content - } - - public var hashValue: Int { - return name.hashValue - } -} - - diff --git a/Sources/Tentacle/File.swift b/Sources/Tentacle/File.swift index d0e975c..f61148b 100644 --- a/Sources/Tentacle/File.swift +++ b/Sources/Tentacle/File.swift @@ -55,18 +55,9 @@ public struct File: ResourceType, Encodable { try container.encode(content.base64EncodedString(), forKey: .content) try container.encode(branch, forKey: .branch) } -} -extension File: Hashable { + // Hashable public var hashValue: Int { return message.hashValue } - - public static func ==(lhs: File, rhs: File) -> Bool { - return lhs.message == rhs.message - && lhs.committer == rhs.committer - && lhs.author == rhs.committer - && lhs.content == rhs.content - && lhs.branch == rhs.branch - } } diff --git a/Sources/Tentacle/FileResponse.swift b/Sources/Tentacle/FileResponse.swift index 76584e9..7bc7859 100644 --- a/Sources/Tentacle/FileResponse.swift +++ b/Sources/Tentacle/FileResponse.swift @@ -15,13 +15,3 @@ public struct FileResponse: ResourceType { /// Commit associated with the file that was created public let commit: Commit } - -extension FileResponse { - public var hashValue: Int { - return content.hashValue ^ commit.hashValue - } - - public static func ==(lhs: FileResponse, rhs: FileResponse) -> Bool { - return true - } -} diff --git a/Sources/Tentacle/GitHubError.swift b/Sources/Tentacle/GitHubError.swift index f4f0807..0ee55ae 100644 --- a/Sources/Tentacle/GitHubError.swift +++ b/Sources/Tentacle/GitHubError.swift @@ -9,7 +9,7 @@ import Foundation /// An error from the GitHub API. -public struct GitHubError: CustomStringConvertible, Error, Decodable { +public struct GitHubError: CustomStringConvertible, Error, ResourceType { /// The error message from the API. public let message: String @@ -21,13 +21,3 @@ public struct GitHubError: CustomStringConvertible, Error, Decodable { self.message = message } } - -extension GitHubError: Hashable { - public static func ==(lhs: GitHubError, rhs: GitHubError) -> Bool { - return lhs.message == rhs.message - } - - public var hashValue: Int { - return message.hashValue - } -} diff --git a/Sources/Tentacle/Identifiable.swift b/Sources/Tentacle/Identifiable.swift index 5245d14..cda828a 100644 --- a/Sources/Tentacle/Identifiable.swift +++ b/Sources/Tentacle/Identifiable.swift @@ -18,7 +18,7 @@ extension Identifiable { } } -public struct ID: Decodable { +public struct ID: Decodable, Hashable { var rawValue: Int public var string: String { @@ -37,19 +37,3 @@ extension ID: ExpressibleByIntegerLiteral { self.rawValue = value } } - -extension ID: Hashable { - - public var hashValue: Int { - return rawValue.hashValue - } - -} - -extension ID: Equatable { - - static public func == (lhs: ID, rhs: ID) -> Bool { - return lhs.rawValue == rhs.rawValue - } - -} diff --git a/Sources/Tentacle/Organization.swift b/Sources/Tentacle/Organization.swift index 4649ee9..adf9064 100644 --- a/Sources/Tentacle/Organization.swift +++ b/Sources/Tentacle/Organization.swift @@ -30,13 +30,3 @@ public struct Organization: CustomStringConvertible, ResourceType { return name } } - -extension Organization: Hashable { - public static func ==(lhs: Organization, rhs: Organization) -> Bool { - return lhs.name == rhs.name - } - - public var hashValue: Int { - return name.hashValue - } -} diff --git a/Sources/Tentacle/PullRequest.swift b/Sources/Tentacle/PullRequest.swift index 407cbe2..6460aac 100644 --- a/Sources/Tentacle/PullRequest.swift +++ b/Sources/Tentacle/PullRequest.swift @@ -28,13 +28,3 @@ public struct PullRequest: CustomStringConvertible, ResourceType { case patchURL = "patch_url" } } - -extension PullRequest: Hashable { - public static func ==(lhs: PullRequest, rhs: PullRequest) -> Bool { - return lhs.url == rhs.url - } - - public var hashValue: Int { - return url.hashValue - } -} diff --git a/Sources/Tentacle/Request.swift b/Sources/Tentacle/Request.swift index ff28d35..8638eec 100644 --- a/Sources/Tentacle/Request.swift +++ b/Sources/Tentacle/Request.swift @@ -17,7 +17,7 @@ internal enum Method: String { } /// An opaque value representing a request to be made. -public struct Request { +public struct Request: Hashable { internal var method: Method internal var path: String internal var queryItems: [URLQueryItem] @@ -29,20 +29,12 @@ public struct Request { self.queryItems = queryItems self.body = body } -} -extension Request: Hashable { + // Hashable public var hashValue: Int { return method.hashValue ^ path.hashValue ^ queryItems.map { $0.hashValue }.reduce(0, ^) - ^ (self.body?.hashValue ?? 0) - } - - public static func == (lhs: Request, rhs: Request) -> Bool { - return lhs.method == rhs.method - && lhs.path == rhs.path - && lhs.queryItems == rhs.queryItems - && lhs.body == rhs.body + ^ (body?.hashValue ?? 0) } } diff --git a/Sources/Tentacle/Response.swift b/Sources/Tentacle/Response.swift index d646a38..4d42b89 100644 --- a/Sources/Tentacle/Response.swift +++ b/Sources/Tentacle/Response.swift @@ -35,7 +35,7 @@ private func linksInLinkHeader(_ header: String) -> [String: URL] { } /// A response from the GitHub API. -public struct Response { +public struct Response: Hashable { /// The number of requests remaining in the current rate limit window, or nil if the server /// isn't rate-limited. public let rateLimitRemaining: UInt? @@ -61,15 +61,8 @@ public struct Response { .map { Date(timeIntervalSince1970: $0) } self.links = linksInLinkHeader(headerFields["Link"] as String? ?? "") } -} - -extension Response: Hashable { - public static func ==(lhs: Response, rhs: Response) -> Bool { - return lhs.rateLimitRemaining == rhs.rateLimitRemaining - && lhs.rateLimitReset == rhs.rateLimitReset - && lhs.links == rhs.links - } + // Hashable public var hashValue: Int { return (rateLimitRemaining?.hashValue ?? 0) ^ (rateLimitReset?.hashValue ?? 0) diff --git a/Sources/Tentacle/Sha.swift b/Sources/Tentacle/Sha.swift index 038d9c7..eaf0323 100644 --- a/Sources/Tentacle/Sha.swift +++ b/Sources/Tentacle/Sha.swift @@ -22,16 +22,6 @@ public struct SHA: ResourceType, Encodable { } } -extension SHA { - public var hashValue: Int { - return hash.hashValue - } - - public static func ==(lhs: SHA, rhs: SHA) -> Bool { - return lhs.hash == rhs.hash - } -} - extension SHA: ExpressibleByStringLiteral { public init(stringLiteral value: String) { self.hash = value diff --git a/Sources/Tentacle/Tree.swift b/Sources/Tentacle/Tree.swift index fc32ad8..d68004f 100644 --- a/Sources/Tentacle/Tree.swift +++ b/Sources/Tentacle/Tree.swift @@ -173,47 +173,13 @@ public struct Tree: CustomStringConvertible, ResourceType { } } } -} - -extension Tree: Hashable { - public static func ==(lhs: Tree, rhs: Tree) -> Bool { - return lhs.sha == rhs.sha - && lhs.url == rhs.url - && lhs.entries == rhs.entries - && lhs.isTruncated == rhs.isTruncated - } + // Hashable public var hashValue: Int { return sha.hashValue } } -extension Tree.Entry.EntryType: Hashable, Equatable { - public var hashValue: Int { - switch self { - case let .blob(url: url, size: size): - return "blob".hashValue ^ url.hashValue ^ size.hashValue - case let .tree(url): - return "tree".hashValue ^ url.hashValue - case .commit: - return "commit".hashValue - } - } - - static public func ==(lhs: Tree.Entry.EntryType, rhs: Tree.Entry.EntryType) -> Bool { - switch (lhs, rhs) { - case let (.blob(url1, size1), .blob(url2, size2)): - return url1 == url2 && size1 == size2 - case let (.tree(url1), .tree(url2)): - return url1 == url2 - case (.commit, .commit): - return true - default: - return false - } - } -} - extension Tree.Entry: Hashable { public static func ==(lhs: Tree.Entry, rhs: Tree.Entry) -> Bool { return lhs.sha == rhs.sha diff --git a/Sources/Tentacle/User.swift b/Sources/Tentacle/User.swift index fa42777..f015ffa 100644 --- a/Sources/Tentacle/User.swift +++ b/Sources/Tentacle/User.swift @@ -55,7 +55,7 @@ extension User { } /// A user on GitHub or GitHub Enterprise. -public struct User: CustomStringConvertible, Decodable { +public struct User: CustomStringConvertible, ResourceType { /// The user's login/username. public let login: String @@ -68,16 +68,6 @@ public struct User: CustomStringConvertible, Decodable { } } -extension User: Hashable { - public static func ==(lhs: User, rhs: User) -> Bool { - return lhs.login == rhs.login - } - - public var hashValue: Int { - return login.hashValue - } -} - /// Information about a user on GitHub. public struct UserInfo: CustomStringConvertible, ResourceType, Identifiable { public enum UserType: String, Decodable { @@ -130,15 +120,6 @@ public struct UserInfo: CustomStringConvertible, ResourceType, Identifiable { } } -extension UserInfo: Equatable { - public static func ==(lhs: UserInfo, rhs: UserInfo) -> Bool { - return lhs.id == rhs.id - && lhs.user == rhs.user - && lhs.url == rhs.url - && lhs.avatarURL == rhs.avatarURL - } -} - /// Extended information about a user on GitHub. public struct UserProfile: ResourceType { /// The user that this information refers to. @@ -193,20 +174,9 @@ public struct UserProfile: ResourceType { case websiteURL = "blog" case company } -} - -extension UserProfile: Hashable { - public static func ==(lhs: UserProfile, rhs: UserProfile) -> Bool { - return lhs.user == rhs.user - && lhs.joinedDate == rhs.joinedDate - && lhs.name == rhs.name - && lhs.email == rhs.email - && lhs.websiteURL == rhs.websiteURL - && lhs.company == rhs.company - } + // Hashable public var hashValue: Int { return user.hashValue } } -