Skip to content

Commit 5d69d2a

Browse files
add hashable generator with test
1 parent b1330e0 commit 5d69d2a

File tree

6 files changed

+158
-2
lines changed

6 files changed

+158
-2
lines changed

CodeGenerator.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@
4848
A08C585C1E13C5AA00034B76 /* ClosureType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08C585A1E13C5AA00034B76 /* ClosureType.swift */; };
4949
A08C585E1E13CB8300034B76 /* SwiftType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08C585D1E13CB8300034B76 /* SwiftType.swift */; };
5050
A08C585F1E13CB8300034B76 /* SwiftType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08C585D1E13CB8300034B76 /* SwiftType.swift */; };
51+
A0A02CC31E1A60EA001900DC /* Generator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A02CC21E1A60EA001900DC /* Generator.swift */; };
52+
A0A02CC51E1A616C001900DC /* HashableGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A02CC41E1A616C001900DC /* HashableGenerator.swift */; };
53+
A0A02CC71E1A6868001900DC /* HashableGeneratorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A02CC61E1A6868001900DC /* HashableGeneratorTest.swift */; };
54+
A0A02CC91E1A68D8001900DC /* GeneratedHash.txt in Resources */ = {isa = PBXBuildFile; fileRef = A0A02CC81E1A68D8001900DC /* GeneratedHash.txt */; };
55+
A0A02CCA1E1A6A16001900DC /* HashableGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A02CC41E1A616C001900DC /* HashableGenerator.swift */; };
56+
A0A02CCB1E1A6A3F001900DC /* Generator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A02CC21E1A60EA001900DC /* Generator.swift */; };
5157
A0A82AE71E11571200F27EA3 /* interface1.txt in Resources */ = {isa = PBXBuildFile; fileRef = A0A82AE61E11571200F27EA3 /* interface1.txt */; };
5258
A0A82AE91E11593800F27EA3 /* interface1Mock.txt in Resources */ = {isa = PBXBuildFile; fileRef = A0A82AE81E11593800F27EA3 /* interface1Mock.txt */; };
5359
A0A82AEB1E1159C200F27EA3 /* NSObject+file.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A82AEA1E1159C200F27EA3 /* NSObject+file.swift */; };
@@ -134,6 +140,10 @@
134140
A07FE2811E108D6900809837 /* InterfaceMockerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterfaceMockerTests.swift; sourceTree = "<group>"; };
135141
A08C585A1E13C5AA00034B76 /* ClosureType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClosureType.swift; sourceTree = "<group>"; };
136142
A08C585D1E13CB8300034B76 /* SwiftType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftType.swift; sourceTree = "<group>"; };
143+
A0A02CC21E1A60EA001900DC /* Generator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Generator.swift; sourceTree = "<group>"; };
144+
A0A02CC41E1A616C001900DC /* HashableGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HashableGenerator.swift; sourceTree = "<group>"; };
145+
A0A02CC61E1A6868001900DC /* HashableGeneratorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HashableGeneratorTest.swift; sourceTree = "<group>"; };
146+
A0A02CC81E1A68D8001900DC /* GeneratedHash.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GeneratedHash.txt; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
137147
A0A82AE61E11571200F27EA3 /* interface1.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = interface1.txt; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
138148
A0A82AE81E11593800F27EA3 /* interface1Mock.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = interface1Mock.txt; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
139149
A0A82AEA1E1159C200F27EA3 /* NSObject+file.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSObject+file.swift"; sourceTree = "<group>"; };
@@ -248,12 +258,14 @@
248258
A0A82B1B1E127E9F00F27EA3 /* AccessLevelTests.swift */,
249259
A0A82AEE1E11676B00F27EA3 /* SwiftTypeTests.swift */,
250260
A0636FD51E1299100008CE98 /* EquatableGeneratorTests.swift */,
261+
A0A02CC61E1A6868001900DC /* HashableGeneratorTest.swift */,
251262
A0A82AEA1E1159C200F27EA3 /* NSObject+file.swift */,
252263
A0A82AE61E11571200F27EA3 /* interface1.txt */,
253264
A0A82AE81E11593800F27EA3 /* interface1Mock.txt */,
254265
A03920701E0F3A7B005A6E89 /* Info.plist */,
255266
A0636FD71E12997C0008CE98 /* EquatableClazz.txt */,
256267
A0636FD91E1299A80008CE98 /* GeneratedEquals.txt */,
268+
A0A02CC81E1A68D8001900DC /* GeneratedHash.txt */,
257269
A04453D21E156A080063CB99 /* funcMock.txt */,
258270
);
259271
path = CodeGeneratorTests;
@@ -294,7 +306,9 @@
294306
A0636FD21E12944B0008CE98 /* Equatable */ = {
295307
isa = PBXGroup;
296308
children = (
309+
A0A02CC21E1A60EA001900DC /* Generator.swift */,
297310
A0636FD31E1294650008CE98 /* EquatableGenerator.swift */,
311+
A0A02CC41E1A616C001900DC /* HashableGenerator.swift */,
298312
);
299313
name = Equatable;
300314
sourceTree = "<group>";
@@ -418,6 +432,7 @@
418432
isa = PBXResourcesBuildPhase;
419433
buildActionMask = 2147483647;
420434
files = (
435+
A0A02CC91E1A68D8001900DC /* GeneratedHash.txt in Resources */,
421436
A0A82AE91E11593800F27EA3 /* interface1Mock.txt in Resources */,
422437
A0636FDA1E1299A80008CE98 /* GeneratedEquals.txt in Resources */,
423438
A0A82AE71E11571200F27EA3 /* interface1.txt in Resources */,
@@ -457,6 +472,8 @@
457472
A0A82B1D1E127F1000F27EA3 /* AccessLevel.swift in Sources */,
458473
A08C585E1E13CB8300034B76 /* SwiftType.swift in Sources */,
459474
A0636FDB1E129B3E0008CE98 /* EquatableGenerator.swift in Sources */,
475+
A0A02CCA1E1A6A16001900DC /* HashableGenerator.swift in Sources */,
476+
A0A02CCB1E1A6A3F001900DC /* Generator.swift in Sources */,
460477
A0E276661E1542D3003CC557 /* ParamMocker.swift in Sources */,
461478
A01E468D1E1010C100395AED /* FuncParam.swift in Sources */,
462479
);
@@ -468,6 +485,7 @@
468485
files = (
469486
A01E46951E1030E000395AED /* VarSignatureTests.swift in Sources */,
470487
A0A82AEF1E11676B00F27EA3 /* SwiftTypeTests.swift in Sources */,
488+
A0A02CC71E1A6868001900DC /* HashableGeneratorTest.swift in Sources */,
471489
A0636FD61E1299100008CE98 /* EquatableGeneratorTests.swift in Sources */,
472490
A01E467E1E0FE57A00395AED /* InterfaceSignatureTests.swift in Sources */,
473491
A01E46911E1017F100395AED /* FuncSignatureTests.swift in Sources */,
@@ -500,7 +518,9 @@
500518
A0636FD41E1294650008CE98 /* EquatableGenerator.swift in Sources */,
501519
A01E46781E0FE21500395AED /* InterfaceSignature.swift in Sources */,
502520
A01E46831E0FF78300395AED /* InterfaceMocker.swift in Sources */,
521+
A0A02CC51E1A616C001900DC /* HashableGenerator.swift in Sources */,
503522
A03920871E0F3A8B005A6E89 /* GenerateMockCommand.swift in Sources */,
523+
A0A02CC31E1A60EA001900DC /* Generator.swift in Sources */,
504524
A0E2765D1E142670003CC557 /* ParamMocker.swift in Sources */,
505525
A01E468A1E100FB200395AED /* FuncParam.swift in Sources */,
506526
);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
extension EquatableClazz: Hashable {
3+
static func ==(lhs: EquatableClazz, rhs: EquatableClazz) -> Bool {
4+
return lhs.var0 == rhs.var0 && lhs.var1 == rhs.var1 && lhs.var2 == rhs.var2
5+
}
6+
7+
var hashValue: Int {
8+
var hashValue = 1
9+
let hashableVars: [Hashable?] = [var0, var1, var2]
10+
hashableVars.forEach {
11+
hashValue = 31 * hashValue + $0?.hashValue ?? 0
12+
}
13+
return hashValue
14+
}
15+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// HashableGeneratorTest.swift
3+
// CodeGenerator
4+
//
5+
// Created by WANG Jie on 02/01/2017.
6+
// Copyright © 2017 wangjie. All rights reserved.
7+
//
8+
9+
import XCTest
10+
@testable import CodeGenerator
11+
12+
class HashableGeneratorTest: XCTestCase {
13+
override func setUp() {
14+
super.setUp()
15+
// Put setup code here. This method is called before the invocation of each test method in the class.
16+
}
17+
18+
override func tearDown() {
19+
// Put teardown code here. This method is called after the invocation of each test method in the class.
20+
super.tearDown()
21+
}
22+
23+
func testEquatableGenerator() {
24+
let source = string(from: "EquatableClazz", ofType: "txt")
25+
let interface = InterfaceSignature(interfaceSource: source, lines: source.components(separatedBy: "\n"))
26+
let hashableeGenerator = HashableGenerator(interfaceSignature: interface, indentation: " ")
27+
28+
var expectedHashSource = string(from: "GeneratedHash", ofType: "txt").components(separatedBy: "\n")
29+
expectedHashSource.removeLast()
30+
31+
XCTAssertEqual(hashableeGenerator.lines.count, expectedHashSource.count)
32+
let count = min(hashableeGenerator.lines.count, expectedHashSource.count)
33+
for i in 0..<count {
34+
XCTAssertEqual(hashableeGenerator.lines[i], expectedHashSource[i])
35+
}
36+
}
37+
}

Generate.../EquatableGenerator.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import Foundation
1010

11-
struct EquatableGenerator {
11+
struct EquatableGenerator: Generator {
1212
let varSignatures: [VarSignature]
1313
let indentation: String
1414
let interfaceDefinition: InterfaceDefinition
@@ -33,14 +33,20 @@ struct EquatableGenerator {
3333
var lines = [String]()
3434
lines.append("")
3535
lines.append("extension \(interfaceName): Equatable {")
36+
lines.append(contentsOf: equatableLines)
37+
lines.append("}")
38+
return lines
39+
}
40+
41+
var equatableLines: [String] {
42+
var lines = [String]()
3643
lines.append("\(indentation)static func ==(lhs: \(interfaceName), rhs: \(interfaceName)) -> Bool {")
3744
var varsEquals = [String]()
3845
varSignatures.forEach { varSignature in
3946
varsEquals.append("lhs.\(varSignature.name) == rhs.\(varSignature.name)")
4047
}
4148
lines.append("\(indentation)\(indentation)return \(varsEquals.joined(separator: " && "))")
4249
lines.append("\(indentation)}")
43-
lines.append("}")
4450
return lines
4551
}
4652
}

Generate.../Generator.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// Generator.swift
3+
// CodeGenerator
4+
//
5+
// Created by WANG Jie on 02/01/2017.
6+
// Copyright © 2017 wangjie. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
protocol Generator {
12+
var lines: [String] { get }
13+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//
2+
// HashableGenerator.swift
3+
// CodeGenerator
4+
//
5+
// Created by WANG Jie on 02/01/2017.
6+
// Copyright © 2017 wangjie. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
struct HashableGenerator: Generator {
12+
var equatableGenerator: EquatableGenerator
13+
14+
var interfaceName: String {
15+
return equatableGenerator.interfaceDefinition.name
16+
}
17+
18+
var indentation: String {
19+
return equatableGenerator.indentation
20+
}
21+
22+
var varSignatures: [VarSignature] {
23+
return equatableGenerator.varSignatures
24+
}
25+
26+
init(interfaceSignature: InterfaceSignature, indentation: String) {
27+
self.equatableGenerator = EquatableGenerator(interfaceSignature: interfaceSignature, indentation: indentation)
28+
}
29+
30+
init(interfaceDefinition: InterfaceDefinition, varSignatures: [VarSignature], indentation: String) {
31+
self.equatableGenerator = EquatableGenerator(interfaceDefinition: interfaceDefinition, varSignatures: varSignatures, indentation: indentation)
32+
}
33+
34+
var lines: [String] {
35+
var lines = [String]()
36+
lines.append("")
37+
lines.append("extension \(interfaceName): Hashable {")
38+
lines.append(contentsOf: equatableGenerator.equatableLines)
39+
lines.append("")
40+
lines.append(contentsOf: hashValueLines)
41+
lines.append("}")
42+
return lines
43+
}
44+
45+
var hashValueLines: [String] {
46+
var lines = [String]()
47+
lines.append("\(indentation)var hashValue: Int {")
48+
lines.append("\(indentation)\(indentation)var hashValue = 1")
49+
let hashableVars = varSignatures.map { $0.name }.joined(separator: ", ")
50+
var varsType = "[Hashable]"
51+
var varHash = "$0.hashValue"
52+
if (varSignatures.filter { $0.type.isOptional }).count > 0 {
53+
varsType = "[Hashable?]"
54+
varHash = "$0?.hashValue ?? 0"
55+
}
56+
lines.append("\(indentation)\(indentation)let hashableVars: \(varsType) = [\(hashableVars)]")
57+
58+
lines.append("\(indentation)\(indentation)hashableVars.forEach {")
59+
lines.append("\(indentation)\(indentation)\(indentation)hashValue = 31 * hashValue + \(varHash)")
60+
lines.append("\(indentation)\(indentation)}")
61+
lines.append("\(indentation)\(indentation)return hashValue")
62+
lines.append("\(indentation)}")
63+
return lines
64+
}
65+
}

0 commit comments

Comments
 (0)