Compare commits
1 Commits
master
...
feature/sw
Author | SHA1 | Date |
---|---|---|
![]() |
dcf7358b19 |
|
@ -0,0 +1 @@
|
|||
Generator/lib_InternalSwiftSyntaxParser.xcframework.zip filter=lfs diff=lfs merge=lfs -text
|
|
@ -33,12 +33,11 @@ Generator/*.app
|
|||
cuckoo_generator
|
||||
.fastlane
|
||||
|
||||
Generator/CuckooGenerator.xcodeproj
|
||||
Cuckoo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
|
||||
Cuckoo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
|
||||
Cuckoo.xcworkspace
|
||||
Cuckoo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
|
||||
|
||||
Tuist/Dependencies/graph.json
|
||||
Tuist/Dependencies/Carthage
|
||||
|
@ -48,3 +47,4 @@ Tuist/Dependencies/Cocoapods
|
|||
Generator/Generator.xcodeproj
|
||||
|
||||
Generator/GeneratedMocks.swift
|
||||
Generator/lib_InternalSwiftSyntaxParser.xcframework
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/nvzqz/FileKit.git",
|
||||
"state" : {
|
||||
"branch" : "develop",
|
||||
"revision" : "6937ec38b0c383b0505caeea6603e62086bf5431"
|
||||
"revision" : "9006d2888025fbe893c3c396327b2fe45a8c177b",
|
||||
"version" : "6.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -54,15 +54,6 @@
|
|||
"version" : "4.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "sourcekitten",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/jpsim/SourceKitten.git",
|
||||
"state" : {
|
||||
"revision" : "79ca340f609adee48defa966e6a3dd0e0acbeb08",
|
||||
"version" : "0.21.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "spectre",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
@ -77,26 +68,53 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/kylef/Stencil.git",
|
||||
"state" : {
|
||||
"revision" : "ccd9402682f4c07dac9561befd207c8156e80e20",
|
||||
"version" : "0.14.2"
|
||||
"revision" : "4f222ac85d673f35df29962fc4c36ccfdaf9da5b",
|
||||
"version" : "0.15.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swxmlhash",
|
||||
"identity" : "swift-argument-parser",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/drmohundro/SWXMLHash.git",
|
||||
"location" : "https://github.com/apple/swift-argument-parser.git",
|
||||
"state" : {
|
||||
"revision" : "f43166a8e18fdd0857f29e303b1bb79a5428bca0",
|
||||
"version" : "4.9.0"
|
||||
"revision" : "9f39744e025c7d377987f30b03770805dcb0bcd1",
|
||||
"version" : "1.1.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "yams",
|
||||
"identity" : "swift-format",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/jpsim/Yams.git",
|
||||
"location" : "https://github.com/apple/swift-format.git",
|
||||
"state" : {
|
||||
"revision" : "b08dba4bcea978bf1ad37703a384097d3efce5af",
|
||||
"version" : "1.0.2"
|
||||
"revision" : "5f184220d032a019a63df457cdea4b9c8241e911",
|
||||
"version" : "0.50700.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-syntax",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-syntax.git",
|
||||
"state" : {
|
||||
"revision" : "72d3da66b085c2299dd287c2be3b92b5ebd226de",
|
||||
"version" : "0.50700.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-system",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-system.git",
|
||||
"state" : {
|
||||
"revision" : "836bc4557b74fe6d2660218d56e3ce96aff76574",
|
||||
"version" : "1.1.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-tools-support-core",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-tools-support-core.git",
|
||||
"state" : {
|
||||
"revision" : "4f07be3dc201f6e2ee85b6942d0c220a16926811",
|
||||
"version" : "0.2.7"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -9,7 +9,7 @@ Pod::Spec.new do |s|
|
|||
|
||||
s.homepage = "https://github.com/Brightify/Cuckoo"
|
||||
s.license = 'MIT'
|
||||
s.author = { "Tadeas Kriz" => "tadeas@brightify.org", "Filip Dolnik" => "filip@brightify.org", "Adriaan (Arjan) Duijzer" => "arjan@nxtstep.nl" }
|
||||
s.author = { "Matyas Kriz" => "m@tyas.cz", "Tadeas Kriz" => "tadeas@brightify.org", "Filip Dolnik" => "filip@brightify.org", "Adriaan (Arjan) Duijzer" => "arjan@nxtstep.nl" }
|
||||
s.source = {
|
||||
:git => "https://github.com/Brightify/Cuckoo.git",
|
||||
:tag => s.version.to_s
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
09C45035E8B83C11AF029E91 /* Stub.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4758812545462B94DAB7A4 /* Stub.swift */; };
|
||||
0A3DB4FDAAF378953FE620F2 /* CallMatcherFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC319F6F55C00CFD3D0AF96 /* CallMatcherFunctions.swift */; };
|
||||
0A63C1802D5BBDCCFB91DE3A /* StubFunctionThenCallRealImplementationTrait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5319F82EEAE3868CE8F23172 /* StubFunctionThenCallRealImplementationTrait.swift */; };
|
||||
0BEB6AA4984EF02EA3A6AA00 /* NestedSubclassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C4A20137742161D649D3E3B /* NestedSubclassTest.swift */; };
|
||||
0BFE2DDD3E06D51F9B297E07 /* ToBeStubbedReadOnlyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 375E2C8E10768E1A9A04C362 /* ToBeStubbedReadOnlyProperty.swift */; };
|
||||
0C2B108704AEB93556C4B0CE /* StubNoReturnFunctionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7635A46FDE48804E6E21EC0 /* StubNoReturnFunctionTest.swift */; };
|
||||
0D789EF876584F271908B424 /* StubNoReturnFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 700931036CB43C60AEFB7FEB /* StubNoReturnFunction.swift */; };
|
||||
|
@ -49,6 +50,7 @@
|
|||
116D8FBB03787C2D7F7C99CC /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8F1FB05574F9DB1A4CE7AB3 /* TestError.swift */; };
|
||||
11700496E1D2DF02E9CD49BE /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B81133817083F2B8122BE188 /* XCTest.framework */; };
|
||||
11B3B5F6FFF87351410F8B43 /* ToBeStubbedReadOnlyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 375E2C8E10768E1A9A04C362 /* ToBeStubbedReadOnlyProperty.swift */; };
|
||||
11B3F573CEAEDBC88BDC8AFF /* NestedSubclassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C4A20137742161D649D3E3B /* NestedSubclassTest.swift */; };
|
||||
1261E976B71C9A806A73DA9D /* CreateMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44692276AAFF9261EDD5D75 /* CreateMock.swift */; };
|
||||
138FB34F332E9076D2C30FDC /* NSObjectProtocolInheritanceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FBE411D64C1D2B056E42C52 /* NSObjectProtocolInheritanceTest.swift */; };
|
||||
13A6FF70A68C12E237C85B4C /* StubFunctionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBF18CC12259A96D05F579B /* StubFunctionTest.swift */; };
|
||||
|
@ -64,6 +66,7 @@
|
|||
18A8AA3E4C7365AB6658D626 /* Dictionary+matchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6975D97C79395805A3BB3B04 /* Dictionary+matchers.swift */; };
|
||||
18A918338118AE7B7FDDDD8E /* TestedSubProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3E7F562DC17ECF3B32CBB3 /* TestedSubProtocol.swift */; };
|
||||
1B0F180FCABE289F64EF37B6 /* DefaultValueRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190FB7FABF7486D2963F4B44 /* DefaultValueRegistry.swift */; };
|
||||
1B35986E55804D8DFE6FC061 /* Pods_Cuckoo_OCMock_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F87AB6F574DC47448E8F3863 /* Pods_Cuckoo_OCMock_tvOS.framework */; };
|
||||
1B425DF3B416C5E4FA04532C /* ArgumentCaptorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76DE925DA03AAA0FD9734CFE /* ArgumentCaptorTest.swift */; };
|
||||
1B57B5A8CEAD3FFB218A379B /* Stub.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE4758812545462B94DAB7A4 /* Stub.swift */; };
|
||||
1B6BDFF7EF9B2385D50910C3 /* MultiNestedClassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002B2852C62F702127A3D24E /* MultiNestedClassTest.swift */; };
|
||||
|
@ -89,6 +92,7 @@
|
|||
25611F1843D374BB1840D16B /* NestedStructExtensionClassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0512EFCB8EDE906B3E54057B /* NestedStructExtensionClassTest.swift */; };
|
||||
25B3658FB7569F94794BC8E7 /* StubNoReturnFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 700931036CB43C60AEFB7FEB /* StubNoReturnFunction.swift */; };
|
||||
25D818649F9686990D6E25AF /* StubTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40FB9A410020B1B90952823C /* StubTest.swift */; };
|
||||
2647BA750CED383CE3439905 /* Pods_Cuckoo_OCMock_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D77AB55B3A73709BDA8437F0 /* Pods_Cuckoo_OCMock_iOS.framework */; };
|
||||
2711CAFD8EEBC32B4991A237 /* StubNoReturnFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 700931036CB43C60AEFB7FEB /* StubNoReturnFunction.swift */; };
|
||||
2728634862DD41A1F558CE7F /* ExcludedStubTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F2852ABE97CC059DD98D13 /* ExcludedStubTest.swift */; };
|
||||
27645AF0AE6BE0B714E4A7A8 /* StubFunctionThenThrowTrait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 201DFAD306F0F1B18CE9EFBE /* StubFunctionThenThrowTrait.swift */; };
|
||||
|
@ -107,7 +111,6 @@
|
|||
2E54AB548933FF3D2F7E1384 /* DefaultValueRegistryTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E80D1401CB6046B1AEDBE204 /* DefaultValueRegistryTest.swift */; };
|
||||
2FA8B5B7D3DBD836A3FE9694 /* ObjectiveArgumentClosure.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6D63F5E63DF9302E70BF764 /* ObjectiveArgumentClosure.swift */; };
|
||||
2FB87BFE2FFBCF459D35DF5E /* MockManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91992FE8D38A6900C005B0A4 /* MockManager.swift */; };
|
||||
3083E891A8AA06D2D571B18C /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DD3286025BB166116AD2BAE /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework */; };
|
||||
3172B5B4F28F82A9393194EE /* StubCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA3EB970DE7CF1D83AC121F /* StubCall.swift */; };
|
||||
31968C424EAAE213191924C0 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 648E1DCC3FA05944AC970663 /* XCTest.framework */; };
|
||||
31EC7665C1236E34B1B21642 /* OCMockObject+CuckooMockObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EE3E19406E96533EBBBD138 /* OCMockObject+CuckooMockObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
|
@ -119,6 +122,7 @@
|
|||
355E1D135C0ABDEE2521647D /* ToBeStubbedReadOnlyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 375E2C8E10768E1A9A04C362 /* ToBeStubbedReadOnlyProperty.swift */; };
|
||||
35A2CEA0553DFBABD2391BBB /* NestedExtensionClassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29F42B443F090072DFF751FD /* NestedExtensionClassTest.swift */; };
|
||||
35AB01E0F9979120DD4E385A /* CallMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C854CC76B478ED72B6D3A65 /* CallMatcher.swift */; };
|
||||
35DB3CFDF76FAFC186CCF5E5 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 194F548C24DA8152FAEAE7E9 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework */; };
|
||||
35E0698113191B077A7C0B24 /* CuckooFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 938B3F655E8E20AB6D341A0D /* CuckooFunctions.swift */; };
|
||||
35FFC4C64E3C99174A7E7E91 /* ThreadLocal.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB65661C2188A3E830EEBF72 /* ThreadLocal.swift */; };
|
||||
360F056E5B1803C9CFE68DA3 /* StubAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29C647EAE09B6AB55FF6C0CE /* StubAction.swift */; };
|
||||
|
@ -164,7 +168,6 @@
|
|||
49397518100C50FB12E4D57E /* ParameterMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A843913B61AB11A80097F51 /* ParameterMatcher.swift */; };
|
||||
4979C7CD6F921D3627A7DB83 /* NestedStructTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 245F73FBA37EA0E055BA4EA2 /* NestedStructTest.swift */; };
|
||||
4A0037995B682F70C67C1839 /* StubFunctionThenCallRealImplementationTrait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5319F82EEAE3868CE8F23172 /* StubFunctionThenCallRealImplementationTrait.swift */; };
|
||||
4A62B192708AD7476317E384 /* Pods_Cuckoo_OCMock_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CCFC4929BB6578E62C06913A /* Pods_Cuckoo_OCMock_tvOS.framework */; };
|
||||
4A6C033747BA78251DE47F48 /* ParameterMatcherFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6CA2236A30B54754F335DC3 /* ParameterMatcherFunctions.swift */; };
|
||||
4A91D2B262ED9EC2EAC65D85 /* ExcludedTestClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB36E482FF288D775B744A02 /* ExcludedTestClass.swift */; };
|
||||
4B94FF7B55E04D0177ED4770 /* ThreadLocal.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB65661C2188A3E830EEBF72 /* ThreadLocal.swift */; };
|
||||
|
@ -241,7 +244,6 @@
|
|||
718886B6E9C79E094F9A472B /* ParameterMatcherFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6CA2236A30B54754F335DC3 /* ParameterMatcherFunctions.swift */; };
|
||||
71C2BCE31CA3B6FCD55224AA /* Dictionary+matchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6975D97C79395805A3BB3B04 /* Dictionary+matchers.swift */; };
|
||||
71E5A49D8F6F49CFDECEA3D5 /* StubbingProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A9BEFC601EF66DF42D5022 /* StubbingProxy.swift */; };
|
||||
7357129D17477272975CBCBC /* NestedSubclassTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E654F50A34B51CD16E76A2 /* NestedSubclassTests.swift */; };
|
||||
73B01B742C366190692DC3F2 /* VerifyReadOnlyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A08AF20C937EF4EB98795B /* VerifyReadOnlyProperty.swift */; };
|
||||
73C243460EAE2D834DA55E94 /* ObjectiveCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 654DD2C28B20B62C30F20699 /* ObjectiveCatcher.m */; };
|
||||
73ECEBE34D54DE64870F9020 /* StubThrowingFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 808091A975F4E8BDDF0C80D9 /* StubThrowingFunction.swift */; };
|
||||
|
@ -276,6 +278,7 @@
|
|||
827A670BF9391A7C01822AF1 /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8F1FB05574F9DB1A4CE7AB3 /* TestError.swift */; };
|
||||
83A5A8205205BF4D44F93CD0 /* ArgumentCaptorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76DE925DA03AAA0FD9734CFE /* ArgumentCaptorTest.swift */; };
|
||||
8443421090DA81C2C68570A1 /* Cuckoo_OCMock_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD83449ACABE73EE786CA3E3 /* Cuckoo_OCMock_macOS.framework */; };
|
||||
84A7C123934DF31E3CB48DF1 /* Pods_Cuckoo_OCMock_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6EAF21976FCFA3343C232939 /* Pods_Cuckoo_OCMock_macOS.framework */; };
|
||||
84CF3EB0CA4FDF5F01BB6847 /* OCMockObject+Workaround.h in Headers */ = {isa = PBXBuildFile; fileRef = 95B3E26DA5700FCAF7286B16 /* OCMockObject+Workaround.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84E115FC5DA7BC43B2751E6E /* GenericProtocolTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 905EC88A402004B01C6FE73E /* GenericProtocolTest.swift */; };
|
||||
85804B9F05012E7EA4659860 /* UnavailablePlatformClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6665FD7C16558B821564AADB /* UnavailablePlatformClass.swift */; };
|
||||
|
@ -300,7 +303,6 @@
|
|||
8C61162C8AFDB8D153798DBC /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 648E1DCC3FA05944AC970663 /* XCTest.framework */; };
|
||||
8CB6ABE1F6EB68B5F081CD2A /* NestedClassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3646D56C8005FB7E1B11B67 /* NestedClassTest.swift */; };
|
||||
8D80FA22DC7306DD02A3E6E0 /* StubNoReturnThrowingFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = D920573D13B938FEACFF82C6 /* StubNoReturnThrowingFunction.swift */; };
|
||||
8EABFB3D5035C5628E0B0A1B /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A8232B39A1033045A35B60A /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework */; };
|
||||
8EC6901E5D2329815A954132 /* BaseStubFunctionTrait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B55AC80C790F69750B2F80 /* BaseStubFunctionTrait.swift */; };
|
||||
8F64666ABEA12593621A1E5B /* StubFunctionThenTrait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C749F49256DDA51A9C96C9 /* StubFunctionThenTrait.swift */; };
|
||||
8FCE701ABF6436EA73A75767 /* CallMatcherFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC319F6F55C00CFD3D0AF96 /* CallMatcherFunctions.swift */; };
|
||||
|
@ -323,6 +325,7 @@
|
|||
97F6BD5C658631C6B86F13E8 /* ArgumentCaptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94FEF459CF7A13B3FC66D390 /* ArgumentCaptor.swift */; };
|
||||
9820ACF2D223E8C1DE7CB9CE /* StubNoReturnThrowingFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = D920573D13B938FEACFF82C6 /* StubNoReturnThrowingFunction.swift */; };
|
||||
98833B16634285BFDA764222 /* MultiNestedInExtensionFromClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB894FF725838C4DE9FFDC9A /* MultiNestedInExtensionFromClass.swift */; };
|
||||
992E1CFD5221BEB55CD337FF /* NestedSubclassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C4A20137742161D649D3E3B /* NestedSubclassTest.swift */; };
|
||||
993AC06E43973AF2E8DB5A1B /* ObjectiveArgumentClosure.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6D63F5E63DF9302E70BF764 /* ObjectiveArgumentClosure.swift */; };
|
||||
996F90892116045116104676 /* Cuckoo_OCMock_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DD5D3471880E656BEA0A210 /* Cuckoo_OCMock_iOS.framework */; platformFilter = ios; };
|
||||
9A973F6AD57DD908C9D75B9B /* __DoNotUse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511DD0B1EA1EAF535C598A8C /* __DoNotUse.swift */; };
|
||||
|
@ -376,6 +379,7 @@
|
|||
B4CABEBF620374BC06D2823B /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55014A1A85497F2153371D7 /* TestUtils.swift */; };
|
||||
B4D4670EAA09DA5A79BB11AB /* MockManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91992FE8D38A6900C005B0A4 /* MockManager.swift */; };
|
||||
B4FFDFFB75D194453AE2D175 /* StubCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA3EB970DE7CF1D83AC121F /* StubCall.swift */; };
|
||||
B576F1274DC3407E43F86C8A /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F21B45333B1857F3854D779 /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework */; };
|
||||
B626F2DA221BF968E127B54A /* VerifyReadOnlyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A08AF20C937EF4EB98795B /* VerifyReadOnlyProperty.swift */; };
|
||||
B648456E51B3FF8CB037B3B5 /* Matchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C633EBD6E6E6568FE9B40567 /* Matchable.swift */; };
|
||||
B6C4CC5A967C0CC567A9F454 /* MockManager+preconfigured.swift in Sources */ = {isa = PBXBuildFile; fileRef = E83C4A633699E5B88D9A9C1B /* MockManager+preconfigured.swift */; };
|
||||
|
@ -390,7 +394,6 @@
|
|||
BA5FFE5076C1E8B3CD590D77 /* GenericMethodClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E584CAC626A3E38BC45E773 /* GenericMethodClass.swift */; };
|
||||
BA6739666F5DDC4ADA564E2C /* GenericClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F01C5ABA73DC1B0CCE088669 /* GenericClass.swift */; };
|
||||
BAA6262023C7BBD7F945FA91 /* ObjectiveVerify.swift in Sources */ = {isa = PBXBuildFile; fileRef = 107C9243167200396831A18F /* ObjectiveVerify.swift */; };
|
||||
BB289937FFF493E53DBF7FE8 /* NestedSubclassTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E654F50A34B51CD16E76A2 /* NestedSubclassTests.swift */; };
|
||||
BB2E89CC430EFA7009FFFD47 /* StubFunctionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBF18CC12259A96D05F579B /* StubFunctionTest.swift */; };
|
||||
BBA5EEAD87D96D3B15C78757 /* CollisionClasses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CDB969240E4E2B12FF93284 /* CollisionClasses.swift */; };
|
||||
BBAC0B12C70D9B414A0E93E1 /* VerifyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753FC6D19235B2C8F2DBAA7B /* VerifyProperty.swift */; };
|
||||
|
@ -418,7 +421,6 @@
|
|||
C918EF1A82AE3300CFD0178C /* Cuckoo-BridgingHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = A78767AF78A5705F914CB5F1 /* Cuckoo-BridgingHeader.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C98DD2231948D6D9486E3C1C /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55014A1A85497F2153371D7 /* TestUtils.swift */; };
|
||||
CA88A2D7512A9EE0D64D6879 /* StubbingProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A9BEFC601EF66DF42D5022 /* StubbingProxy.swift */; };
|
||||
CB4F2E994373AF88A32748D3 /* Pods_Cuckoo_OCMock_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02E7D093817E7CE04A04C2AF /* Pods_Cuckoo_OCMock_macOS.framework */; };
|
||||
CB95B245036865240B20E448 /* MultiLayeredNestedTestedSubclassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F0DF66BC063943C91FB2C3 /* MultiLayeredNestedTestedSubclassTest.swift */; };
|
||||
CBB7017EE143A38098AD7287 /* GenericMethodClassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B965102D09D6B0E94CDA8EA /* GenericMethodClassTest.swift */; };
|
||||
CC2BA5A130CB61216E489D99 /* VerifyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 753FC6D19235B2C8F2DBAA7B /* VerifyProperty.swift */; };
|
||||
|
@ -479,16 +481,13 @@
|
|||
EA58B9A4A3DDB81EBB31BC26 /* OCMockObject+CuckooMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D732D63C18B4DE267CB365CF /* OCMockObject+CuckooMockObject.m */; };
|
||||
EAFA72896871E0A2629AC784 /* ClassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6873C8013002AFEA7565BDAC /* ClassTest.swift */; };
|
||||
EB12D8BACB131BD4DF064AF0 /* ObjectiveMatchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70C4FAE3318E21F0A87531A /* ObjectiveMatchers.swift */; };
|
||||
EB37DBF5C5EEB81AE40E203F /* Pods_Cuckoo_OCMock_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAAC201DCB53797CB6435DB1 /* Pods_Cuckoo_OCMock_iOS.framework */; };
|
||||
EB3BC2A3CB2C8FA24CA01B18 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09B97C65DA87366B8605109 /* Utils.swift */; };
|
||||
ECED2B81290B73C2EC6D70A5 /* NestedInNestedStruct.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90E9A4C6A1716C6D219D26E /* NestedInNestedStruct.swift */; };
|
||||
ECFFBD0F7DB6DD452B542425 /* NestedPrivateExtensionClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECFED3C29F5CA48398AF0C5B /* NestedPrivateExtensionClass.swift */; };
|
||||
ED2DFFFD32E3D5EC061C89DA /* ClassWithUnavailablePlatformMembers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FB937EA0F029B222D748FED /* ClassWithUnavailablePlatformMembers.swift */; };
|
||||
ED34902303F797CACE7C47FC /* StubFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82D83797450CB57EC3E0A693 /* StubFunction.swift */; };
|
||||
ED9646245798F318CAD33E12 /* NestedSubclassTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E654F50A34B51CD16E76A2 /* NestedSubclassTests.swift */; };
|
||||
EDD2EDC801189CF637948AA4 /* DefaultValueRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190FB7FABF7486D2963F4B44 /* DefaultValueRegistry.swift */; };
|
||||
EEF3DC22DC7212C654EF328D /* __DoNotUse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511DD0B1EA1EAF535C598A8C /* __DoNotUse.swift */; };
|
||||
EFB24DDC33700188444EA5F0 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6E045C7BF96B0FF85FAE2988 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework */; };
|
||||
EFB5C46F8B4DFE1801EA6114 /* StubThrowingFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 808091A975F4E8BDDF0C80D9 /* StubThrowingFunction.swift */; };
|
||||
F01B6FF9BCFEED923AFCE5FC /* CallMatcherTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F445E0EFD2FD1FBC888DB72 /* CallMatcherTest.swift */; };
|
||||
F09C7E5B6AD4AEB0166F871F /* ClassWithOptionals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32A299482E4D2B7B774373A1 /* ClassWithOptionals.swift */; };
|
||||
|
@ -514,6 +513,7 @@
|
|||
F7F9CC2F71A29EFD3670D387 /* NSObjectProtocolInheritanceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FBE411D64C1D2B056E42C52 /* NSObjectProtocolInheritanceTest.swift */; };
|
||||
F8540250669374FFC11720A2 /* StubbingProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A9BEFC601EF66DF42D5022 /* StubbingProxy.swift */; };
|
||||
F86949BD502D4EBFC978FC24 /* NestedInExtensionFromClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9699C3284544FE817C78E474 /* NestedInExtensionFromClass.swift */; };
|
||||
F93AE8CCD2CF4BD1FFAAAC70 /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 598FA7C4C26C7322B25F1358 /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework */; };
|
||||
F98A5E661D992AB274733FAF /* MockManager+preconfigured.swift in Sources */ = {isa = PBXBuildFile; fileRef = E83C4A633699E5B88D9A9C1B /* MockManager+preconfigured.swift */; };
|
||||
FA4E1EA6ED897418E81B360F /* StubFunctionThenThrowingTrait.swift in Sources */ = {isa = PBXBuildFile; fileRef = F398C1D87D71EE8DED0C6EA3 /* StubFunctionThenThrowingTrait.swift */; };
|
||||
FA7B45FA1AD8F9CA07CC8506 /* NSObject+TrustMe.m in Sources */ = {isa = PBXBuildFile; fileRef = E0656C5164A529DCCADBA8F1 /* NSObject+TrustMe.m */; };
|
||||
|
@ -696,7 +696,7 @@
|
|||
/* Begin PBXFileReference section */
|
||||
002B2852C62F702127A3D24E /* MultiNestedClassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiNestedClassTest.swift; sourceTree = "<group>"; };
|
||||
01496A793103612242EE7A04 /* VerificationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerificationTest.swift; sourceTree = "<group>"; };
|
||||
02E7D093817E7CE04A04C2AF /* Pods_Cuckoo_OCMock_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
02EAAA14360EE993DF2A2AA3 /* Pods-Cuckoo_OCMock-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-iOS.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-iOS/Pods-Cuckoo_OCMock-iOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
03A9BEFC601EF66DF42D5022 /* StubbingProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubbingProxy.swift; sourceTree = "<group>"; };
|
||||
03AF60404FD2D5FD3198825E /* StubRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubRecorder.swift; sourceTree = "<group>"; };
|
||||
03B55AC80C790F69750B2F80 /* BaseStubFunctionTrait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseStubFunctionTrait.swift; sourceTree = "<group>"; };
|
||||
|
@ -706,12 +706,14 @@
|
|||
09F0DF66BC063943C91FB2C3 /* MultiLayeredNestedTestedSubclassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiLayeredNestedTestedSubclassTest.swift; sourceTree = "<group>"; };
|
||||
0A933D33D55AE257FE9B1097 /* ObjectiveStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectiveStub.swift; sourceTree = "<group>"; };
|
||||
0BEF42DC82FC0EF50E83E6CA /* CuckooFunctionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CuckooFunctionsTest.swift; sourceTree = "<group>"; };
|
||||
0FCC7E0CFC29DFD7C97EB8FC /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
107C9243167200396831A18F /* ObjectiveVerify.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectiveVerify.swift; sourceTree = "<group>"; };
|
||||
119D4E6C9798F70CEBDBB1F2 /* TestedClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestedClass.swift; sourceTree = "<group>"; };
|
||||
18D8112F0A64A41ED070EA9F /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
190FB7FABF7486D2963F4B44 /* DefaultValueRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultValueRegistry.swift; sourceTree = "<group>"; };
|
||||
194F548C24DA8152FAEAE7E9 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1A843913B61AB11A80097F51 /* ParameterMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParameterMatcher.swift; sourceTree = "<group>"; };
|
||||
1B965102D09D6B0E94CDA8EA /* GenericMethodClassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericMethodClassTest.swift; sourceTree = "<group>"; };
|
||||
1DCDA7E7A2DA0E7AD149208B /* Pods-Cuckoo_OCMock-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-macOS.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-macOS/Pods-Cuckoo_OCMock-macOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
1E13C3DFFA9A3676F92404B7 /* Cuckoo_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Cuckoo_macOS.framework; path = Cuckoo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
201DFAD306F0F1B18CE9EFBE /* StubFunctionThenThrowTrait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubFunctionThenThrowTrait.swift; sourceTree = "<group>"; };
|
||||
245F73FBA37EA0E055BA4EA2 /* NestedStructTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedStructTest.swift; sourceTree = "<group>"; };
|
||||
|
@ -721,14 +723,14 @@
|
|||
29F42B443F090072DFF751FD /* NestedExtensionClassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedExtensionClassTest.swift; sourceTree = "<group>"; };
|
||||
2C68FC814ACBD3D5E1C7ED1B /* StubFunctionThenDoNothingTrait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubFunctionThenDoNothingTrait.swift; sourceTree = "<group>"; };
|
||||
2F445E0EFD2FD1FBC888DB72 /* CallMatcherTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMatcherTest.swift; sourceTree = "<group>"; };
|
||||
2FC3CF194933ED399D9483E2 /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
30EE51B1225328733D4F5DBA /* Cuckoo_OCMock-macOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo_OCMock-macOS-Info.plist"; sourceTree = "<group>"; };
|
||||
3191519C8ED4DD5B3D439A93 /* StubFunctionThenReturnTrait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubFunctionThenReturnTrait.swift; sourceTree = "<group>"; };
|
||||
323D9BB2B0A99E0408471845 /* Pods-Cuckoo_OCMock-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-iOS.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-iOS/Pods-Cuckoo_OCMock-iOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
32A299482E4D2B7B774373A1 /* ClassWithOptionals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassWithOptionals.swift; sourceTree = "<group>"; };
|
||||
33EBD5D113A20F38FCE13BDC /* Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mock.swift; sourceTree = "<group>"; };
|
||||
355C36C0536DBF7EDA3C2B96 /* ObjcProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjcProtocol.swift; sourceTree = "<group>"; };
|
||||
375E2C8E10768E1A9A04C362 /* ToBeStubbedReadOnlyProperty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToBeStubbedReadOnlyProperty.swift; sourceTree = "<group>"; };
|
||||
3A8232B39A1033045A35B60A /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3B4C9565EA304E2CF62B1D4F /* Pods-Cuckoo_OCMock-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-macOS.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-macOS/Pods-Cuckoo_OCMock-macOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
3C3E2B1C12FF95C6DCA418D5 /* ObjectiveCatcher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjectiveCatcher.h; sourceTree = "<group>"; };
|
||||
3CD1EF95EED208CF56D123F8 /* Cuckoo_OCMock_tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Cuckoo_OCMock_tvOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3D1D814F035D5D39FC84D26C /* Array+matchers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+matchers.swift"; sourceTree = "<group>"; };
|
||||
|
@ -741,9 +743,9 @@
|
|||
511DD0B1EA1EAF535C598A8C /* __DoNotUse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = __DoNotUse.swift; sourceTree = "<group>"; };
|
||||
5319F82EEAE3868CE8F23172 /* StubFunctionThenCallRealImplementationTrait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubFunctionThenCallRealImplementationTrait.swift; sourceTree = "<group>"; };
|
||||
55DE1954C1D6E94F2911830A /* ClassForStubTesting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassForStubTesting.swift; sourceTree = "<group>"; };
|
||||
55E654F50A34B51CD16E76A2 /* NestedSubclassTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedSubclassTests.swift; sourceTree = "<group>"; };
|
||||
5673B933A24CA65D15B3FD3A /* CallMatcherFunctionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMatcherFunctionsTest.swift; sourceTree = "<group>"; };
|
||||
58E1385A0AB0BD61D0DFD5C1 /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
5776F80847FB1775D23C8064 /* Pods-Cuckoo_OCMock-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-tvOS/Pods-Cuckoo_OCMock-tvOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
598FA7C4C26C7322B25F1358 /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
5A67E79E73B4710B3C846F96 /* StubNoReturnThrowingFunctionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubNoReturnThrowingFunctionTest.swift; sourceTree = "<group>"; };
|
||||
5BA3EB970DE7CF1D83AC121F /* StubCall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubCall.swift; sourceTree = "<group>"; };
|
||||
5CC319F6F55C00CFD3D0AF96 /* CallMatcherFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMatcherFunctions.swift; sourceTree = "<group>"; };
|
||||
|
@ -751,15 +753,14 @@
|
|||
648E1DCC3FA05944AC970663 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
|
||||
64F2852ABE97CC059DD98D13 /* ExcludedStubTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExcludedStubTest.swift; sourceTree = "<group>"; };
|
||||
654DD2C28B20B62C30F20699 /* ObjectiveCatcher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjectiveCatcher.m; sourceTree = "<group>"; };
|
||||
65F7304C5992843A0A5D3863 /* Pods-Cuckoo_OCMock-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-macOS.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-macOS/Pods-Cuckoo_OCMock-macOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
6665FD7C16558B821564AADB /* UnavailablePlatformClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnavailablePlatformClass.swift; sourceTree = "<group>"; };
|
||||
6873C8013002AFEA7565BDAC /* ClassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassTest.swift; sourceTree = "<group>"; };
|
||||
6975D97C79395805A3BB3B04 /* Dictionary+matchers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+matchers.swift"; sourceTree = "<group>"; };
|
||||
6978339A31BEDF22A4115E81 /* ProtocolTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolTest.swift; sourceTree = "<group>"; };
|
||||
6C0DC4D2D6B0E6C61B27E90E /* Stubber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stubber.swift; sourceTree = "<group>"; };
|
||||
6DBE7A13FEE1B8C7EE8DA363 /* Cuckoo-macOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo-macOS-Info.plist"; sourceTree = "<group>"; };
|
||||
6E045C7BF96B0FF85FAE2988 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6E4033B8F0022DDDDA758351 /* Pods-Cuckoo_OCMock-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-tvOS.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-tvOS/Pods-Cuckoo_OCMock-tvOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
6EAF21976FCFA3343C232939 /* Pods_Cuckoo_OCMock_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6F21B45333B1857F3854D779 /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
700931036CB43C60AEFB7FEB /* StubNoReturnFunction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubNoReturnFunction.swift; sourceTree = "<group>"; };
|
||||
7054833FFF0D253B1E2379FA /* MultiNestedInNestedClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiNestedInNestedClass.swift; sourceTree = "<group>"; };
|
||||
70AE18F5D3419D1025D081CA /* ParameterMatcherTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParameterMatcherTest.swift; sourceTree = "<group>"; };
|
||||
|
@ -771,18 +772,19 @@
|
|||
7BA242F7A830953CD5E4AC4A /* StringProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StringProxy.m; sourceTree = "<group>"; };
|
||||
7CBF18CC12259A96D05F579B /* StubFunctionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubFunctionTest.swift; sourceTree = "<group>"; };
|
||||
7F29DC9C5F5CCE01FEAE648D /* MultiNestedExtensionClassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiNestedExtensionClassTest.swift; sourceTree = "<group>"; };
|
||||
7FE031A1E54FBEBABC465F88 /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
808091A975F4E8BDDF0C80D9 /* StubThrowingFunction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubThrowingFunction.swift; sourceTree = "<group>"; };
|
||||
82D83797450CB57EC3E0A693 /* StubFunction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubFunction.swift; sourceTree = "<group>"; };
|
||||
83908D3F58736F1C6DA7B2CA /* GenericClassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericClassTest.swift; sourceTree = "<group>"; };
|
||||
866CED1C72D1F35C10251CCC /* NSObjectProtocolInheritanceTesting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSObjectProtocolInheritanceTesting.swift; sourceTree = "<group>"; };
|
||||
86D638696C1458550D4524F1 /* Cuckoo_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Cuckoo_tvOS.framework; path = Cuckoo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8B40CC43D7A77DFD4702178A /* MultiNestedPrivateExtensionClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiNestedPrivateExtensionClass.swift; sourceTree = "<group>"; };
|
||||
8C4A20137742161D649D3E3B /* NestedSubclassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedSubclassTest.swift; sourceTree = "<group>"; };
|
||||
8C854CC76B478ED72B6D3A65 /* CallMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMatcher.swift; sourceTree = "<group>"; };
|
||||
8CDB969240E4E2B12FF93284 /* CollisionClasses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollisionClasses.swift; sourceTree = "<group>"; };
|
||||
8FAA0AEFE10E214A84C0E8EA /* Cuckoo_OCMock-iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo_OCMock-iOS-Info.plist"; sourceTree = "<group>"; };
|
||||
8FBE411D64C1D2B056E42C52 /* NSObjectProtocolInheritanceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSObjectProtocolInheritanceTest.swift; sourceTree = "<group>"; };
|
||||
905EC88A402004B01C6FE73E /* GenericProtocolTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericProtocolTest.swift; sourceTree = "<group>"; };
|
||||
90AE2C9146A1126EC1109B2B /* Pods-Cuckoo_OCMock-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-tvOS/Pods-Cuckoo_OCMock-tvOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
90CA6A2E0084041FD2CA4DD9 /* Cuckoo_tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Cuckoo_tvOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
91992FE8D38A6900C005B0A4 /* MockManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockManager.swift; sourceTree = "<group>"; };
|
||||
919EA0D2C416F1E4F22DAC20 /* NestedInPrivateNestedClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedInPrivateNestedClass.swift; sourceTree = "<group>"; };
|
||||
|
@ -793,8 +795,8 @@
|
|||
9699C3284544FE817C78E474 /* NestedInExtensionFromClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedInExtensionFromClass.swift; sourceTree = "<group>"; };
|
||||
96C749F49256DDA51A9C96C9 /* StubFunctionThenTrait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubFunctionThenTrait.swift; sourceTree = "<group>"; };
|
||||
989EFADEC10AB6D627A5FAE6 /* NSValueConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSValueConvertible.swift; sourceTree = "<group>"; };
|
||||
99D050972B5669B5B58E9DE7 /* Pods-Cuckoo_OCMock-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-tvOS.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-tvOS/Pods-Cuckoo_OCMock-tvOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
9C0889A597AF4CCA8841B471 /* MockBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBuilder.swift; sourceTree = "<group>"; };
|
||||
9DD3286025BB166116AD2BAE /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9DD5D3471880E656BEA0A210 /* Cuckoo_OCMock_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Cuckoo_OCMock_iOS.framework; path = Cuckoo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9DE5DC1B6EC0BF686019517B /* UnavailablePlatformProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnavailablePlatformProtocol.swift; sourceTree = "<group>"; };
|
||||
9E584CAC626A3E38BC45E773 /* GenericMethodClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericMethodClass.swift; sourceTree = "<group>"; };
|
||||
|
@ -802,12 +804,13 @@
|
|||
A21CD7B8ADE5ABE0295581D4 /* VerificationProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerificationProxy.swift; sourceTree = "<group>"; };
|
||||
A398D6337F320A5F78FA4A5A /* GenericProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericProtocol.swift; sourceTree = "<group>"; };
|
||||
A78767AF78A5705F914CB5F1 /* Cuckoo-BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Cuckoo-BridgingHeader.h"; sourceTree = "<group>"; };
|
||||
A83242F5AF363867836B8970 /* Pods-Cuckoo_OCMock-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-iOS.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-iOS/Pods-Cuckoo_OCMock-iOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
AC30579DC4B1D5D5CC959724 /* Cuckoo-iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo-iOS-Info.plist"; sourceTree = "<group>"; };
|
||||
AD3E7F562DC17ECF3B32CBB3 /* TestedSubProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestedSubProtocol.swift; sourceTree = "<group>"; };
|
||||
AE4758812545462B94DAB7A4 /* Stub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stub.swift; sourceTree = "<group>"; };
|
||||
B30A194A634E5972418D171E /* Mocked.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mocked.swift; sourceTree = "<group>"; };
|
||||
B6098DE536CCBA16747765FD /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B6B86DCAC6958FF36DF3639C /* ParameterMatcherFunctionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParameterMatcherFunctionsTest.swift; sourceTree = "<group>"; };
|
||||
B712732E2656B55EDE652691 /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
B81133817083F2B8122BE188 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
|
||||
B9813FA38F8AB71BEE454CF4 /* Cuckoo-iOSTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo-iOSTests-Info.plist"; sourceTree = "<group>"; };
|
||||
BA8CA90EAB7BD8AB7F5840D0 /* Cuckoo_OCMock-macOSTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo_OCMock-macOSTests-Info.plist"; sourceTree = "<group>"; };
|
||||
|
@ -820,27 +823,27 @@
|
|||
C55014A1A85497F2153371D7 /* TestUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUtils.swift; sourceTree = "<group>"; };
|
||||
C61C355CDFD7F0A7C0F32A25 /* NSInvocation+OCMockWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSInvocation+OCMockWrapper.m"; sourceTree = "<group>"; };
|
||||
C633EBD6E6E6568FE9B40567 /* Matchable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Matchable.swift; sourceTree = "<group>"; };
|
||||
C6A3C8DF4AD4DE7807F60B62 /* Pods-Cuckoo_OCMock-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-macOS.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-macOS/Pods-Cuckoo_OCMock-macOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
C6D63F5E63DF9302E70BF764 /* ObjectiveArgumentClosure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectiveArgumentClosure.swift; sourceTree = "<group>"; };
|
||||
C8D7931D2C7E8A64861A1863 /* OCMockObject+Workaround.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OCMockObject+Workaround.m"; sourceTree = "<group>"; };
|
||||
C8EEC51ACDE645FA676CB016 /* Cuckoo-macOSTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo-macOSTests-Info.plist"; sourceTree = "<group>"; };
|
||||
C90E9A4C6A1716C6D219D26E /* NestedInNestedStruct.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedInNestedStruct.swift; sourceTree = "<group>"; };
|
||||
C9525C20EA498D59BFCE3F7B /* ObjectiveAssertThrows.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectiveAssertThrows.swift; sourceTree = "<group>"; };
|
||||
CB65661C2188A3E830EEBF72 /* ThreadLocal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadLocal.swift; sourceTree = "<group>"; };
|
||||
CCFC4929BB6578E62C06913A /* Pods_Cuckoo_OCMock_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CEBE505B4B98BE6289678CD1 /* MatchableTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchableTest.swift; sourceTree = "<group>"; };
|
||||
D09B97C65DA87366B8605109 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
|
||||
D4108DD343B556BAA2BC0501 /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D3399F3F2FE04AE3E357B548 /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D44692276AAFF9261EDD5D75 /* CreateMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateMock.swift; sourceTree = "<group>"; };
|
||||
D535CF4BAE6BA1CA7220CDB7 /* Set+matchers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Set+matchers.swift"; sourceTree = "<group>"; };
|
||||
D732D63C18B4DE267CB365CF /* OCMockObject+CuckooMockObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OCMockObject+CuckooMockObject.m"; sourceTree = "<group>"; };
|
||||
D7635A46FDE48804E6E21EC0 /* StubNoReturnFunctionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubNoReturnFunctionTest.swift; sourceTree = "<group>"; };
|
||||
D77AB55B3A73709BDA8437F0 /* Pods_Cuckoo_OCMock_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D7A08AF20C937EF4EB98795B /* VerifyReadOnlyProperty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerifyReadOnlyProperty.swift; sourceTree = "<group>"; };
|
||||
D920573D13B938FEACFF82C6 /* StubNoReturnThrowingFunction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubNoReturnThrowingFunction.swift; sourceTree = "<group>"; };
|
||||
DA0F20F08A3C63CB00D2E7E4 /* TestedSubclass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestedSubclass.swift; sourceTree = "<group>"; };
|
||||
DAFDD79179243CBB217358C7 /* TestedProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestedProtocol.swift; sourceTree = "<group>"; };
|
||||
DD83449ACABE73EE786CA3E3 /* Cuckoo_OCMock_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Cuckoo_OCMock_macOS.framework; path = Cuckoo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E0656C5164A529DCCADBA8F1 /* NSObject+TrustMe.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+TrustMe.m"; sourceTree = "<group>"; };
|
||||
E13C3B0AD475F81DE8BBB18D /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
E216B22B63CECBFA5F681510 /* Cuckoo-tvOSTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo-tvOSTests-Info.plist"; sourceTree = "<group>"; };
|
||||
E3646D56C8005FB7E1B11B67 /* NestedClassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedClassTest.swift; sourceTree = "<group>"; };
|
||||
E4A99A2173E7F7743145B11B /* GeneratedMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneratedMocks.swift; sourceTree = "<group>"; };
|
||||
|
@ -852,17 +855,14 @@
|
|||
ECFED3C29F5CA48398AF0C5B /* NestedPrivateExtensionClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedPrivateExtensionClass.swift; sourceTree = "<group>"; };
|
||||
EE5F4691EE101415724C1D73 /* Cuckoo_OCMock-iOSTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo_OCMock-iOSTests-Info.plist"; sourceTree = "<group>"; };
|
||||
F01C5ABA73DC1B0CCE088669 /* GenericClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericClass.swift; sourceTree = "<group>"; };
|
||||
F2B26467F81DC89FAA7E0C15 /* Pods-Cuckoo_OCMock-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-iOS.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-iOS/Pods-Cuckoo_OCMock-iOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
F398C1D87D71EE8DED0C6EA3 /* StubFunctionThenThrowingTrait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubFunctionThenThrowingTrait.swift; sourceTree = "<group>"; };
|
||||
F3C87227E4CAE60FD9202D6F /* NSInvocation+OCMockWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSInvocation+OCMockWrapper.h"; sourceTree = "<group>"; };
|
||||
F6CA2236A30B54754F335DC3 /* ParameterMatcherFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParameterMatcherFunctions.swift; sourceTree = "<group>"; };
|
||||
F70C4FAE3318E21F0A87531A /* ObjectiveMatchers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectiveMatchers.swift; sourceTree = "<group>"; };
|
||||
F81B5143E65D60134B59CFA4 /* Cuckoo_OCMock-tvOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Cuckoo_OCMock-tvOS-Info.plist"; sourceTree = "<group>"; };
|
||||
F9735ACE5BF868774A356231 /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
F87AB6F574DC47448E8F3863 /* Pods_Cuckoo_OCMock_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F981A41C0D53F5AF59BD7202 /* Cuckoo_OCMock_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Cuckoo_OCMock_tvOS.framework; path = Cuckoo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FAAC201DCB53797CB6435DB1 /* Pods_Cuckoo_OCMock_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Cuckoo_OCMock_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FB36E482FF288D775B744A02 /* ExcludedTestClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExcludedTestClass.swift; sourceTree = "<group>"; };
|
||||
FD600CEE1B82473FC8F31F06 /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig"; path = "Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
FE705433C346CA3DF4E2AB96 /* ToBeStubbedProperty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToBeStubbedProperty.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -896,7 +896,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8C61162C8AFDB8D153798DBC /* XCTest.framework in Frameworks */,
|
||||
CB4F2E994373AF88A32748D3 /* Pods_Cuckoo_OCMock_macOS.framework in Frameworks */,
|
||||
84A7C123934DF31E3CB48DF1 /* Pods_Cuckoo_OCMock_macOS.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -905,7 +905,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
11700496E1D2DF02E9CD49BE /* XCTest.framework in Frameworks */,
|
||||
EB37DBF5C5EEB81AE40E203F /* Pods_Cuckoo_OCMock_iOS.framework in Frameworks */,
|
||||
2647BA750CED383CE3439905 /* Pods_Cuckoo_OCMock_iOS.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -914,7 +914,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3CFAA76E52C3382D06DDDB7A /* Cuckoo_OCMock_tvOS.framework in Frameworks */,
|
||||
8EABFB3D5035C5628E0B0A1B /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework in Frameworks */,
|
||||
F93AE8CCD2CF4BD1FFAAAC70 /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -923,7 +923,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8443421090DA81C2C68570A1 /* Cuckoo_OCMock_macOS.framework in Frameworks */,
|
||||
3083E891A8AA06D2D571B18C /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework in Frameworks */,
|
||||
B576F1274DC3407E43F86C8A /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -948,7 +948,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
996F90892116045116104676 /* Cuckoo_OCMock_iOS.framework in Frameworks */,
|
||||
EFB24DDC33700188444EA5F0 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework in Frameworks */,
|
||||
35DB3CFDF76FAFC186CCF5E5 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -957,7 +957,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
48C1BD8F4E0BA4C6CA1D76D3 /* XCTest.framework in Frameworks */,
|
||||
4A62B192708AD7476317E384 /* Pods_Cuckoo_OCMock_tvOS.framework in Frameworks */,
|
||||
1B35986E55804D8DFE6FC061 /* Pods_Cuckoo_OCMock_tvOS.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -1015,7 +1015,7 @@
|
|||
B9E2517ABB4C90F2E8FA4696 /* Project */,
|
||||
FEEC9B8DBF0FA8678CE815E0 /* Frameworks */,
|
||||
512C697A5D123B937FE97812 /* Products */,
|
||||
49C7C79888FCE0DEB1110FBF /* Pods */,
|
||||
312C3FBE428B8E2EAEB1851F /* Pods */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
@ -1044,6 +1044,25 @@
|
|||
path = OCMock;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
312C3FBE428B8E2EAEB1851F /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
02EAAA14360EE993DF2A2AA3 /* Pods-Cuckoo_OCMock-iOS.debug.xcconfig */,
|
||||
A83242F5AF363867836B8970 /* Pods-Cuckoo_OCMock-iOS.release.xcconfig */,
|
||||
E13C3B0AD475F81DE8BBB18D /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig */,
|
||||
2FC3CF194933ED399D9483E2 /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig */,
|
||||
1DCDA7E7A2DA0E7AD149208B /* Pods-Cuckoo_OCMock-macOS.debug.xcconfig */,
|
||||
3B4C9565EA304E2CF62B1D4F /* Pods-Cuckoo_OCMock-macOS.release.xcconfig */,
|
||||
D3399F3F2FE04AE3E357B548 /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig */,
|
||||
B712732E2656B55EDE652691 /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig */,
|
||||
5776F80847FB1775D23C8064 /* Pods-Cuckoo_OCMock-tvOS.debug.xcconfig */,
|
||||
99D050972B5669B5B58E9DE7 /* Pods-Cuckoo_OCMock-tvOS.release.xcconfig */,
|
||||
18D8112F0A64A41ED070EA9F /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig */,
|
||||
7FE031A1E54FBEBABC465F88 /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
422FE57E963E63B12F0FE722 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1081,25 +1100,6 @@
|
|||
path = Verification;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
49C7C79888FCE0DEB1110FBF /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
323D9BB2B0A99E0408471845 /* Pods-Cuckoo_OCMock-iOS.debug.xcconfig */,
|
||||
F2B26467F81DC89FAA7E0C15 /* Pods-Cuckoo_OCMock-iOS.release.xcconfig */,
|
||||
F9735ACE5BF868774A356231 /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig */,
|
||||
0FCC7E0CFC29DFD7C97EB8FC /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig */,
|
||||
C6A3C8DF4AD4DE7807F60B62 /* Pods-Cuckoo_OCMock-macOS.debug.xcconfig */,
|
||||
65F7304C5992843A0A5D3863 /* Pods-Cuckoo_OCMock-macOS.release.xcconfig */,
|
||||
B6098DE536CCBA16747765FD /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig */,
|
||||
FD600CEE1B82473FC8F31F06 /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig */,
|
||||
90AE2C9146A1126EC1109B2B /* Pods-Cuckoo_OCMock-tvOS.debug.xcconfig */,
|
||||
6E4033B8F0022DDDDA758351 /* Pods-Cuckoo_OCMock-tvOS.release.xcconfig */,
|
||||
D4108DD343B556BAA2BC0501 /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig */,
|
||||
58E1385A0AB0BD61D0DFD5C1 /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
512C697A5D123B937FE97812 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1179,7 +1179,7 @@
|
|||
29F42B443F090072DFF751FD /* NestedExtensionClassTest.swift */,
|
||||
0512EFCB8EDE906B3E54057B /* NestedStructExtensionClassTest.swift */,
|
||||
245F73FBA37EA0E055BA4EA2 /* NestedStructTest.swift */,
|
||||
55E654F50A34B51CD16E76A2 /* NestedSubclassTests.swift */,
|
||||
8C4A20137742161D649D3E3B /* NestedSubclassTest.swift */,
|
||||
8FBE411D64C1D2B056E42C52 /* NSObjectProtocolInheritanceTest.swift */,
|
||||
6978339A31BEDF22A4115E81 /* ProtocolTest.swift */,
|
||||
40FB9A410020B1B90952823C /* StubTest.swift */,
|
||||
|
@ -1354,12 +1354,12 @@
|
|||
7AEF1D77E05D83F84ADE7A87 /* XCTest.framework */,
|
||||
B81133817083F2B8122BE188 /* XCTest.framework */,
|
||||
648E1DCC3FA05944AC970663 /* XCTest.framework */,
|
||||
FAAC201DCB53797CB6435DB1 /* Pods_Cuckoo_OCMock_iOS.framework */,
|
||||
6E045C7BF96B0FF85FAE2988 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework */,
|
||||
02E7D093817E7CE04A04C2AF /* Pods_Cuckoo_OCMock_macOS.framework */,
|
||||
9DD3286025BB166116AD2BAE /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework */,
|
||||
CCFC4929BB6578E62C06913A /* Pods_Cuckoo_OCMock_tvOS.framework */,
|
||||
3A8232B39A1033045A35B60A /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework */,
|
||||
D77AB55B3A73709BDA8437F0 /* Pods_Cuckoo_OCMock_iOS.framework */,
|
||||
194F548C24DA8152FAEAE7E9 /* Pods_Cuckoo_OCMock_iOS_Cuckoo_OCMock_iOSTests.framework */,
|
||||
6EAF21976FCFA3343C232939 /* Pods_Cuckoo_OCMock_macOS.framework */,
|
||||
6F21B45333B1857F3854D779 /* Pods_Cuckoo_OCMock_macOS_Cuckoo_OCMock_macOSTests.framework */,
|
||||
F87AB6F574DC47448E8F3863 /* Pods_Cuckoo_OCMock_tvOS.framework */,
|
||||
598FA7C4C26C7322B25F1358 /* Pods_Cuckoo_OCMock_tvOS_Cuckoo_OCMock_tvOSTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1416,12 +1416,12 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D8D9738C622AC77A0AD3C99C /* Build configuration list for PBXNativeTarget "Cuckoo_OCMock-tvOSTests" */;
|
||||
buildPhases = (
|
||||
D8E9D790042A7DBC669415D7 /* [CP] Check Pods Manifest.lock */,
|
||||
86009F31E41824C4A0083178 /* [CP] Check Pods Manifest.lock */,
|
||||
DCFCE738380747FA90A17E02 /* Sources */,
|
||||
44A58B8F3B45191E95CE2650 /* Resources */,
|
||||
EE7B717FA1BFB5D77F7E37E0 /* Embed Frameworks */,
|
||||
52AD199FB7C4B081CEB16EB7 /* Frameworks */,
|
||||
F482EEC2B5D59227E33C620A /* [CP] Embed Pods Frameworks */,
|
||||
4106A0A5BDAC832E1023D35A /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -1455,12 +1455,12 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 4975D1A314DF2F3B03921C05 /* Build configuration list for PBXNativeTarget "Cuckoo_OCMock-iOSTests" */;
|
||||
buildPhases = (
|
||||
B599DCB12CAA3A87441791B0 /* [CP] Check Pods Manifest.lock */,
|
||||
A6DC8CD047E92A889E2B1B49 /* [CP] Check Pods Manifest.lock */,
|
||||
DA8CF62D0B45947696C7CA57 /* Sources */,
|
||||
9F5A861AA4A648E0AA8CBAF3 /* Resources */,
|
||||
95F067D7C8E3858D9C7B1ACA /* Embed Frameworks */,
|
||||
C5252DF514145309C583BC1C /* Frameworks */,
|
||||
35988EE58868DFADDBA20B3B /* [CP] Embed Pods Frameworks */,
|
||||
83FA9CED63612C063406E51C /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -1476,7 +1476,7 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = BAD574EA9F7BD25327F418C8 /* Build configuration list for PBXNativeTarget "Cuckoo_OCMock-macOS" */;
|
||||
buildPhases = (
|
||||
71CADC9726153BE5F6BB2738 /* [CP] Check Pods Manifest.lock */,
|
||||
95A3031C76FA53D509722E60 /* [CP] Check Pods Manifest.lock */,
|
||||
289CD55941F8375304A0FA40 /* Headers */,
|
||||
97824D7A6F12CE3AE9E4C89E /* Sources */,
|
||||
E5B19CA15C7230C7DB4DEAE8 /* Resources */,
|
||||
|
@ -1554,7 +1554,7 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 431006DE18EB78C97D35651A /* Build configuration list for PBXNativeTarget "Cuckoo_OCMock-iOS" */;
|
||||
buildPhases = (
|
||||
7EB54E19B0ACE9555F9F3054 /* [CP] Check Pods Manifest.lock */,
|
||||
5C621A3A3586D0F695EBD0FE /* [CP] Check Pods Manifest.lock */,
|
||||
36034BCF09BB5C60775B1390 /* Headers */,
|
||||
54DBCB29E77138C0A8DA5AE9 /* Sources */,
|
||||
3A87627B88A1B3B0BACF31A3 /* Resources */,
|
||||
|
@ -1574,7 +1574,7 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D5AB84ECE1C48279A3174C2F /* Build configuration list for PBXNativeTarget "Cuckoo_OCMock-tvOS" */;
|
||||
buildPhases = (
|
||||
6255112D1BC080CF10F6657B /* [CP] Check Pods Manifest.lock */,
|
||||
9AC438C28C07FED842ABB94B /* [CP] Check Pods Manifest.lock */,
|
||||
66785690DDA051B8D848078C /* Headers */,
|
||||
57C722FCE701A7CB8373AF82 /* Sources */,
|
||||
91DE98464C1F3EC6B841B817 /* Resources */,
|
||||
|
@ -1612,12 +1612,12 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 419AB8BB7268955611576ABC /* Build configuration list for PBXNativeTarget "Cuckoo_OCMock-macOSTests" */;
|
||||
buildPhases = (
|
||||
E867028CA93376A28E4C9F0F /* [CP] Check Pods Manifest.lock */,
|
||||
DDCFC473F52E9993F0926955 /* [CP] Check Pods Manifest.lock */,
|
||||
CABDB0580E21EEBE1C06CB8E /* Sources */,
|
||||
DD60C0DD6531B3CCE27D430B /* Resources */,
|
||||
EBE25D5DF2CC2AF1AACF74DF /* Embed Frameworks */,
|
||||
5345EBC8A03A18A6BD0A24AE /* Frameworks */,
|
||||
44FEAE74934993E701CA2BF7 /* [CP] Embed Pods Frameworks */,
|
||||
717E017005E63212DC015EED /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -1773,21 +1773,21 @@
|
|||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
35988EE58868DFADDBA20B3B /* [CP] Embed Pods Frameworks */ = {
|
||||
4106A0A5BDAC832E1023D35A /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests-frameworks.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
42C8B15E53049F2976363441 /* Generate mocks */ = {
|
||||
|
@ -1809,23 +1809,6 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "if [ \"$GENERATE_TEST_MOCKS\" = \"NO\" ] ; then exit; fi\n\n# Make sure the generator is up-to-date.\necho 'Building generator.'\n\"$PROJECT_DIR\"/build_generator\n\necho 'Generating mocks.'\n\"$PROJECT_DIR\"/Generator/bin/cuckoo_generator generate \\\n\t--testable Cuckoo \\\n\t--exclude ExcludedTestClass,ExcludedProtocol \\\n\t--output \"$PROJECT_DIR\"/Tests/Swift/Generated/GeneratedMocks.swift \\\n\t--glob \"$PROJECT_DIR\"/Tests/Swift/Source/*.swift";
|
||||
};
|
||||
44FEAE74934993E701CA2BF7 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
4D36DA407A6B4E6EFDC6DA5F /* Generate mocks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
|
@ -1845,51 +1828,7 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "if [ \"$GENERATE_TEST_MOCKS\" = \"NO\" ] ; then exit; fi\n\n# Make sure the generator is up-to-date.\necho 'Building generator.'\n\"$PROJECT_DIR\"/build_generator\n\necho 'Generating mocks.'\n\"$PROJECT_DIR\"/Generator/bin/cuckoo_generator generate \\\n\t--testable Cuckoo \\\n\t--exclude ExcludedTestClass,ExcludedProtocol \\\n\t--output \"$PROJECT_DIR\"/Tests/Swift/Generated/GeneratedMocks.swift \\\n\t--glob \"$PROJECT_DIR\"/Tests/Swift/Source/*.swift\n";
|
||||
};
|
||||
6255112D1BC080CF10F6657B /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Cuckoo_OCMock-tvOS-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
71CADC9726153BE5F6BB2738 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Cuckoo_OCMock-macOS-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
7EB54E19B0ACE9555F9F3054 /* [CP] Check Pods Manifest.lock */ = {
|
||||
5C621A3A3586D0F695EBD0FE /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -1911,6 +1850,62 @@
|
|||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
717E017005E63212DC015EED /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests/Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
83FA9CED63612C063406E51C /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests/Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
86009F31E41824C4A0083178 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
8E54BA9B8385785DA0BBD4EC /* Generate mocks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
|
@ -1930,7 +1925,51 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "if [ \"$GENERATE_TEST_MOCKS\" = \"NO\" ] ; then exit; fi\n\n# Make sure the generator is up-to-date.\necho 'Building generator.'\n\"$PROJECT_DIR\"/build_generator\n\necho 'Generating mocks.'\n\"$PROJECT_DIR\"/Generator/bin/cuckoo_generator generate \\\n\t--testable Cuckoo \\\n\t--exclude ExcludedTestClass,ExcludedProtocol \\\n\t--output \"$PROJECT_DIR\"/Tests/Swift/Generated/GeneratedMocks.swift \\\n\t--glob \"$PROJECT_DIR\"/Tests/Swift/Source/*.swift";
|
||||
};
|
||||
B599DCB12CAA3A87441791B0 /* [CP] Check Pods Manifest.lock */ = {
|
||||
95A3031C76FA53D509722E60 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Cuckoo_OCMock-macOS-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9AC438C28C07FED842ABB94B /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Cuckoo_OCMock-tvOS-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
A6DC8CD047E92A889E2B1B49 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -1952,29 +1991,7 @@
|
|||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D8E9D790042A7DBC669415D7 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E867028CA93376A28E4C9F0F /* [CP] Check Pods Manifest.lock */ = {
|
||||
DDCFC473F52E9993F0926955 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -1996,23 +2013,6 @@
|
|||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F482EEC2B5D59227E33C620A /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests/Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
@ -2046,7 +2046,7 @@
|
|||
AFBDD93079F30AE78FA0213A /* NestedExtensionClassTest.swift in Sources */,
|
||||
541AE789BEF0830BBBB0A691 /* NestedStructExtensionClassTest.swift in Sources */,
|
||||
4979C7CD6F921D3627A7DB83 /* NestedStructTest.swift in Sources */,
|
||||
7357129D17477272975CBCBC /* NestedSubclassTests.swift in Sources */,
|
||||
992E1CFD5221BEB55CD337FF /* NestedSubclassTest.swift in Sources */,
|
||||
85BB583C1F89B50DC88999F2 /* ProtocolTest.swift in Sources */,
|
||||
BC428931E53499C0EFDC802F /* ClassForStubTesting.swift in Sources */,
|
||||
39B67C20D2A61BF2376634F3 /* ClassWithOptionals.swift in Sources */,
|
||||
|
@ -2237,7 +2237,7 @@
|
|||
B210B6A3EDD5F0807CB635BD /* NestedExtensionClassTest.swift in Sources */,
|
||||
8805AE37A66F847C9DF3206E /* NestedStructExtensionClassTest.swift in Sources */,
|
||||
24563D4813663AB15D24B790 /* NestedStructTest.swift in Sources */,
|
||||
ED9646245798F318CAD33E12 /* NestedSubclassTests.swift in Sources */,
|
||||
0BEB6AA4984EF02EA3A6AA00 /* NestedSubclassTest.swift in Sources */,
|
||||
E22E749D0A0B44EC528CB38F /* ProtocolTest.swift in Sources */,
|
||||
2D2631FF3DFEB17188A08073 /* ClassForStubTesting.swift in Sources */,
|
||||
F52EE531052666CFB50523E6 /* ClassWithOptionals.swift in Sources */,
|
||||
|
@ -2414,7 +2414,7 @@
|
|||
35A2CEA0553DFBABD2391BBB /* NestedExtensionClassTest.swift in Sources */,
|
||||
25611F1843D374BB1840D16B /* NestedStructExtensionClassTest.swift in Sources */,
|
||||
FFCC5303B4F31B8CE8C14BA1 /* NestedStructTest.swift in Sources */,
|
||||
BB289937FFF493E53DBF7FE8 /* NestedSubclassTests.swift in Sources */,
|
||||
11B3F573CEAEDBC88BDC8AFF /* NestedSubclassTest.swift in Sources */,
|
||||
63E990EB0DEE6A4873F30538 /* ProtocolTest.swift in Sources */,
|
||||
A977B902CD0127BCD5BD272F /* ClassForStubTesting.swift in Sources */,
|
||||
F09C7E5B6AD4AEB0166F871F /* ClassWithOptionals.swift in Sources */,
|
||||
|
@ -2621,7 +2621,7 @@
|
|||
/* Begin XCBuildConfiguration section */
|
||||
09A17ABB9CE8D5E803DBC7E5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 58E1385A0AB0BD61D0DFD5C1 /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig */;
|
||||
baseConfigurationReference = 7FE031A1E54FBEBABC465F88 /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
INFOPLIST_FILE = "Derived/InfoPlists/Cuckoo_OCMock-tvOSTests-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
@ -2642,7 +2642,7 @@
|
|||
};
|
||||
0F8DD70D0BDBF0F32D3A5D2A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C6A3C8DF4AD4DE7807F60B62 /* Pods-Cuckoo_OCMock-macOS.debug.xcconfig */;
|
||||
baseConfigurationReference = 1DCDA7E7A2DA0E7AD149208B /* Pods-Cuckoo_OCMock-macOS.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
|
@ -2751,7 +2751,7 @@
|
|||
};
|
||||
6788BA84E4C3F2DF4D49FDD1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 0FCC7E0CFC29DFD7C97EB8FC /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig */;
|
||||
baseConfigurationReference = 2FC3CF194933ED399D9483E2 /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = "Derived/InfoPlists/Cuckoo_OCMock-iOSTests-Info.plist";
|
||||
|
@ -2774,7 +2774,7 @@
|
|||
};
|
||||
68C3608166DB6A5DCC142D0A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D4108DD343B556BAA2BC0501 /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig */;
|
||||
baseConfigurationReference = 18D8112F0A64A41ED070EA9F /* Pods-Cuckoo_OCMock-tvOS-Cuckoo_OCMock-tvOSTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
INFOPLIST_FILE = "Derived/InfoPlists/Cuckoo_OCMock-tvOSTests-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
@ -2828,7 +2828,7 @@
|
|||
};
|
||||
73511D4869AFB48ADC79B8C1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F9735ACE5BF868774A356231 /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig */;
|
||||
baseConfigurationReference = E13C3B0AD475F81DE8BBB18D /* Pods-Cuckoo_OCMock-iOS-Cuckoo_OCMock-iOSTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = "Derived/InfoPlists/Cuckoo_OCMock-iOSTests-Info.plist";
|
||||
|
@ -2883,7 +2883,7 @@
|
|||
};
|
||||
88C896DF3C7EA2C24B2A7B9E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 323D9BB2B0A99E0408471845 /* Pods-Cuckoo_OCMock-iOS.debug.xcconfig */;
|
||||
baseConfigurationReference = 02EAAA14360EE993DF2A2AA3 /* Pods-Cuckoo_OCMock-iOS.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
|
@ -2918,7 +2918,7 @@
|
|||
};
|
||||
8FC167D6E355658B5903183F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 65F7304C5992843A0A5D3863 /* Pods-Cuckoo_OCMock-macOS.release.xcconfig */;
|
||||
baseConfigurationReference = 3B4C9565EA304E2CF62B1D4F /* Pods-Cuckoo_OCMock-macOS.release.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
|
@ -3184,7 +3184,7 @@
|
|||
};
|
||||
C7DB288DC16F2BA0020CA917 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F2B26467F81DC89FAA7E0C15 /* Pods-Cuckoo_OCMock-iOS.release.xcconfig */;
|
||||
baseConfigurationReference = A83242F5AF363867836B8970 /* Pods-Cuckoo_OCMock-iOS.release.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
|
@ -3241,7 +3241,7 @@
|
|||
};
|
||||
D9C80FCB45BF96859CF72662 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B6098DE536CCBA16747765FD /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig */;
|
||||
baseConfigurationReference = D3399F3F2FE04AE3E357B548 /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
INFOPLIST_FILE = "Derived/InfoPlists/Cuckoo_OCMock-macOSTests-Info.plist";
|
||||
|
@ -3283,7 +3283,7 @@
|
|||
};
|
||||
DC200B677208FA5563B50AD7 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 90AE2C9146A1126EC1109B2B /* Pods-Cuckoo_OCMock-tvOS.debug.xcconfig */;
|
||||
baseConfigurationReference = 5776F80847FB1775D23C8064 /* Pods-Cuckoo_OCMock-tvOS.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
|
@ -3339,7 +3339,7 @@
|
|||
};
|
||||
F46AC1AF8E41D78201C5BDE9 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 6E4033B8F0022DDDDA758351 /* Pods-Cuckoo_OCMock-tvOS.release.xcconfig */;
|
||||
baseConfigurationReference = 99D050972B5669B5B58E9DE7 /* Pods-Cuckoo_OCMock-tvOS.release.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
|
@ -3372,7 +3372,7 @@
|
|||
};
|
||||
F4E1D3C8F565E2D98246CF67 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = FD600CEE1B82473FC8F31F06 /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig */;
|
||||
baseConfigurationReference = B712732E2656B55EDE652691 /* Pods-Cuckoo_OCMock-macOS-Cuckoo_OCMock-macOSTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
INFOPLIST_FILE = "Derived/InfoPlists/Cuckoo_OCMock-macOSTests-Info.plist";
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright ©. All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,27 +1,63 @@
|
|||
import ProjectDescription
|
||||
import ProjectDescriptionHelpers
|
||||
|
||||
let target = Target(
|
||||
name: "CuckooGenerator",
|
||||
platform: .macOS,
|
||||
product: .commandLineTool,
|
||||
productName: "cuckoo_generator",
|
||||
bundleId: "CuckooGenerator",
|
||||
deploymentTarget: .macOS(targetVersion: "10.13"),
|
||||
sources: "Sources/**",
|
||||
dependencies: [
|
||||
"FileKit",
|
||||
"Stencil",
|
||||
"Commandant",
|
||||
"SwiftFormat",
|
||||
"SwiftSyntax",
|
||||
"SwiftSyntaxParser",
|
||||
].map(TargetDependency.package(product:)) + [
|
||||
.xcframework(path: "./lib_InternalSwiftSyntaxParser.xcframework")
|
||||
],
|
||||
settings: Settings.settings(
|
||||
base: SettingsDictionary()
|
||||
.otherLinkerFlags([
|
||||
"-Xlinker",
|
||||
"-dead_strip_dylibs",
|
||||
"-dead_strip",
|
||||
])
|
||||
)
|
||||
)
|
||||
|
||||
let testTarget = Target(
|
||||
name: "GeneratorTests",
|
||||
platform: .macOS,
|
||||
product: .unitTests,
|
||||
bundleId: "CuckooGeneratorTests",
|
||||
deploymentTarget: target.deploymentTarget,
|
||||
sources: SourceFilesList(globs: [
|
||||
// TODO: This is wrong but testing CLI is not supported, must separate generator into CLI and internal targets.
|
||||
target.sources?.globs,
|
||||
["Tests/**"],
|
||||
].compactMap { $0 }.flatMap { $0 }),
|
||||
// TODO: This is wrong but testing CLI is not supported, must separate generator into CLI and internal targets.
|
||||
dependencies: target.dependencies
|
||||
)
|
||||
|
||||
// MARK: project definition
|
||||
let project = Project(
|
||||
name: "Generator",
|
||||
options: .options(automaticSchemesOptions: .disabled, disableSynthesizedResourceAccessors: true),
|
||||
packages: [
|
||||
.package(url: "https://github.com/jpsim/SourceKitten.git", .upToNextMinor(from: "0.21.2")),
|
||||
.package(url: "https://github.com/nvzqz/FileKit.git", .branch("develop")),
|
||||
.package(url: "https://github.com/kylef/Stencil.git", .exact("0.14.2")),
|
||||
.package(url: "https://github.com/nvzqz/FileKit.git", .exact("6.1.0")),
|
||||
.package(url: "https://github.com/kylef/Stencil.git", .exact("0.15.1")),
|
||||
.package(url: "https://github.com/Carthage/Commandant.git", .exact("0.15.0")),
|
||||
.package(url: "https://github.com/apple/swift-syntax.git", .exact("0.50700.1")),
|
||||
.package(url: "https://github.com/apple/swift-format.git", .exact("0.50700.1")),
|
||||
],
|
||||
targets: [
|
||||
Target(
|
||||
name: "CuckooGenerator",
|
||||
platform: .macOS,
|
||||
product: .commandLineTool,
|
||||
productName: "cuckoo_generator",
|
||||
bundleId: "CuckooGenerator",
|
||||
deploymentTarget: DeploymentTarget.macOS(targetVersion: "10.13"),
|
||||
sources: "Source/**",
|
||||
dependencies: ["FileKit", "SourceKittenFramework", "Stencil", "Commandant"].map(TargetDependency.package(product:))
|
||||
),
|
||||
target,
|
||||
testTarget,
|
||||
],
|
||||
schemes: [
|
||||
Scheme(
|
||||
|
@ -37,6 +73,7 @@ let project = Project(
|
|||
],
|
||||
runPostActionsOnFailure: false
|
||||
),
|
||||
testAction: TestAction.targets([TestableTarget(target: testTarget.reference)]),
|
||||
runAction: RunAction.runAction(
|
||||
executable: "CuckooGenerator",
|
||||
arguments: Arguments(
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
import Foundation
|
||||
import Commandant
|
||||
import Result
|
||||
|
||||
public struct VersionCommand: CommandProtocol {
|
||||
|
||||
static let appVersion = Bundle.allFrameworks.filter {
|
||||
$0.bundleIdentifier == "org.brightify.CuckooGeneratorFramework"
|
||||
}.first?.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? ""
|
||||
|
||||
public let verb = "version"
|
||||
public let function = "Prints the version of this generator."
|
||||
|
||||
public func run(_ options: Options) -> Result<Void, CuckooGeneratorError> {
|
||||
print(VersionCommand.appVersion)
|
||||
return .success(())
|
||||
}
|
||||
|
||||
public struct Options: OptionsProtocol {
|
||||
public static func evaluate(_ m: CommandMode) -> Result<Options, CommandantError<CuckooGeneratorError>> {
|
||||
return .success(Options())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
import Foundation
|
||||
import FileKit
|
||||
|
||||
public struct FileHeaderHandler {
|
||||
|
||||
public static func getHeader(of file: FileRepresentation, includeTimestamp: Bool) -> String {
|
||||
let path: String
|
||||
if let absolutePath = file.sourceFile.path {
|
||||
path = getRelativePath(from: absolutePath)
|
||||
} else {
|
||||
path = "unknown"
|
||||
}
|
||||
let generationInfo = "// MARK: - Mocks generated from file: \(path)" + (includeTimestamp ? " at \(Date())\n" : "")
|
||||
let header = getHeader(of: file)
|
||||
return generationInfo + "\n" + header + "\n"
|
||||
}
|
||||
|
||||
public static func getImports(of file: FileRepresentation, testableFrameworks: [String]) -> String {
|
||||
var imports = Array(Set(file.declarations.only(Import.self).map { "import \($0.importee)\n" })).sorted().joined(separator: "")
|
||||
if imports.isEmpty == false {
|
||||
imports = "\n\(imports)"
|
||||
}
|
||||
return "import Cuckoo\n" + getTestableImports(testableFrameworks: testableFrameworks) + imports
|
||||
}
|
||||
|
||||
private static func getRelativePath(from absolutePath: String) -> String {
|
||||
let path = Path(absolutePath)
|
||||
let base = path.commonAncestor(Path.current)
|
||||
let components = path.components.suffix(from: base.components.endIndex)
|
||||
let result = components.map { $0.rawValue }.joined(separator: Path.separator)
|
||||
let difference = Path.current.components.endIndex - base.components.endIndex
|
||||
return (0..<difference).reduce(result) { acc, _ in ".." + Path.separator + acc }
|
||||
}
|
||||
|
||||
private static func getHeader(of file: FileRepresentation) -> String {
|
||||
let possibleHeaderEnd = getPossibleHeaderEnd(current: file.sourceFile.contents.unicodeScalars.count, declarations: file.declarations)
|
||||
let possibleHeader = String(file.sourceFile.contents.utf8.prefix(possibleHeaderEnd)) ?? ""
|
||||
let singleLine = getPrefixToLastSingleLineComment(text: possibleHeader)
|
||||
let multiLine = getPrefixToLastMultiLineComment(text: possibleHeader)
|
||||
return singleLine.count > multiLine.count ? singleLine : multiLine
|
||||
}
|
||||
|
||||
private static func getPossibleHeaderEnd(current: Int, declarations: [Token]) -> Int {
|
||||
return declarations.reduce(current) { minimum, declaration in
|
||||
let declarationMinimum: Int
|
||||
switch declaration {
|
||||
case let containerToken as ContainerToken:
|
||||
declarationMinimum = containerToken.range.lowerBound
|
||||
case let method as Method:
|
||||
declarationMinimum = method.range.lowerBound
|
||||
case let importToken as Import:
|
||||
declarationMinimum = importToken.range.lowerBound
|
||||
default:
|
||||
declarationMinimum = minimum
|
||||
}
|
||||
return min(declarationMinimum, minimum)
|
||||
}
|
||||
}
|
||||
|
||||
private static func getPrefixToLastSingleLineComment(text: String) -> String {
|
||||
if let range = text.range(of: "//", options: .backwards) {
|
||||
let lastLine = text.lineRange(for: range)
|
||||
return String(text[..<lastLine.upperBound])
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
private static func getPrefixToLastMultiLineComment(text: String) -> String {
|
||||
if let range = text.range(of: "*/", options: .backwards) {
|
||||
return String(text[..<range.upperBound]) + "\n"
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
private static func getTestableImports(testableFrameworks: [String]) -> String {
|
||||
func replaceIllegalCharacters(_ char: UnicodeScalar) -> Character {
|
||||
if CharacterSet.letters.contains(UnicodeScalar(char.value)!) || CharacterSet.decimalDigits.contains(UnicodeScalar(char.value)!) {
|
||||
return Character(char)
|
||||
} else {
|
||||
return "_"
|
||||
}
|
||||
}
|
||||
return testableFrameworks.map { String($0.unicodeScalars.map(replaceIllegalCharacters)) }.map { "@testable import \($0)\n" }.joined(separator: "")
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
import Foundation
|
||||
import Stencil
|
||||
|
||||
public struct Generator {
|
||||
|
||||
private static let reservedKeywordsNotAllowedAsMethodName: Set = [
|
||||
// Keywords used in declarations:
|
||||
"associatedtype", "class", "deinit", "enum", "extension", "fileprivate", "func", "import", "init", "inout", "internal", "let", "operator", "private", "precedencegroup", "protocol", "public", "rethrows", "static", "struct", "subscript", "typealias", "var",
|
||||
// Keywords used in statements:
|
||||
"break", "case", "catch", "continue", "default", "defer", "do", "else", "fallthrough", "for", "guard", "if", "in", "repeat", "return", "throw", "switch", "where", "while",
|
||||
// Keywords used in expressions and types:
|
||||
"Any", "as", "catch", "false", "is", "nil", "rethrows", "self", "super", "throw", "throws", "true", "try",
|
||||
// Keywords used in patterns:
|
||||
"_",
|
||||
]
|
||||
|
||||
private let declarations: [Token]
|
||||
|
||||
public init(file: FileRepresentation) {
|
||||
declarations = file.declarations
|
||||
}
|
||||
|
||||
public func generate(debug: Bool = false) throws -> String {
|
||||
let ext = Extension()
|
||||
ext.registerFilter("genericSafe") { (value: Any?) in
|
||||
guard let string = value as? String else { return value }
|
||||
return self.genericSafeType(from: string)
|
||||
}
|
||||
|
||||
ext.registerFilter("matchableGenericNames") { (value: Any?) in
|
||||
guard let method = value as? Method else { return value }
|
||||
return self.matchableGenericTypes(from: method)
|
||||
}
|
||||
|
||||
ext.registerFilter("matchableGenericWhereClause") { (value: Any?) in
|
||||
guard let method = value as? Method else { return value }
|
||||
return self.matchableGenericsWhereClause(from: method)
|
||||
}
|
||||
|
||||
ext.registerFilter("matchableParameterSignature") { (value: Any?) in
|
||||
guard let parameters = value as? [MethodParameter] else { return value }
|
||||
return self.matchableParameterSignature(with: parameters)
|
||||
}
|
||||
|
||||
ext.registerFilter("parameterMatchers") { (value: Any?) in
|
||||
guard let parameters = value as? [MethodParameter] else { return value }
|
||||
return self.parameterMatchers(for: parameters)
|
||||
}
|
||||
|
||||
ext.registerFilter("openNestedClosure") { (value: Any?) in
|
||||
guard let method = value as? Method else { return value }
|
||||
return self.openNestedClosure(for: method)
|
||||
}
|
||||
|
||||
ext.registerFilter("closeNestedClosure") { (value: Any?) in
|
||||
guard let parameters = value as? [MethodParameter] else { return value }
|
||||
return self.closeNestedClosure(for: parameters)
|
||||
}
|
||||
|
||||
ext.registerFilter("escapeReservedKeywords") { (value: Any?) in
|
||||
guard let name = value as? String else { return value }
|
||||
return self.escapeReservedKeywords(for: name)
|
||||
}
|
||||
|
||||
ext.registerFilter("removeClosureArgumentNames") { (value: Any?) in
|
||||
guard let type = value as? String else { return value }
|
||||
return self.removeClosureArgumentNames(for: type)
|
||||
}
|
||||
|
||||
let environment = Environment(extensions: [ext])
|
||||
|
||||
let containers = declarations.compactMap { $0 as? ContainerToken }
|
||||
.filter {
|
||||
$0.parent?.areAllHierarchiesAccessible ?? true && $0.accessibility.isAccessible
|
||||
}
|
||||
.map { $0.serializeWithType() }
|
||||
|
||||
return try environment.renderTemplate(string: Templates.mock, context: ["containers": containers, "debug": debug])
|
||||
}
|
||||
|
||||
private func matchableGenericTypes(from method: Method) -> String {
|
||||
guard !method.parameters.isEmpty || !method.genericParameters.isEmpty else { return "" }
|
||||
|
||||
let matchableGenericParameters = method.parameters.enumerated().map { index, parameter -> String in
|
||||
let type = parameter.isOptional ? "OptionalMatchable" : "Matchable"
|
||||
return "M\(index + 1): Cuckoo.\(type)"
|
||||
}
|
||||
let methodGenericParameters = method.genericParameters.map { $0.description }
|
||||
return "<\((matchableGenericParameters + methodGenericParameters).joined(separator: ", "))>"
|
||||
}
|
||||
|
||||
private func matchableGenericsWhereClause(from method: Method) -> String {
|
||||
guard method.parameters.isEmpty == false else { return "" }
|
||||
|
||||
let matchableWhereConstraints = method.parameters.enumerated().map { index, parameter -> String in
|
||||
let type = parameter.isOptional ? "OptionalMatchedType" : "MatchedType"
|
||||
return "M\(index + 1).\(type) == \(genericSafeType(from: parameter.type.withoutAttributes.unoptionaled.sugarized))"
|
||||
}
|
||||
let methodWhereConstraints = method.returnSignature.whereConstraints
|
||||
return " where \((matchableWhereConstraints + methodWhereConstraints).joined(separator: ", "))"
|
||||
}
|
||||
|
||||
private func matchableParameterSignature(with parameters: [MethodParameter]) -> String {
|
||||
guard parameters.isEmpty == false else { return "" }
|
||||
|
||||
return parameters.enumerated().map { "\($1.labelAndName): M\($0 + 1)" }.joined(separator: ", ")
|
||||
}
|
||||
|
||||
private func parameterMatchers(for parameters: [MethodParameter]) -> String {
|
||||
guard parameters.isEmpty == false else { return "let matchers: [Cuckoo.ParameterMatcher<Void>] = []" }
|
||||
|
||||
let tupleType = parameters.map { $0.typeWithoutAttributes }.joined(separator: ", ")
|
||||
let matchers = parameters.enumerated().map { "wrap(matchable: \($1.name)) { $0\(parameters.count > 1 ? ".\($0)" : "") }" }.joined(separator: ", ")
|
||||
return "let matchers: [Cuckoo.ParameterMatcher<(\(genericSafeType(from: tupleType)))>] = [\(matchers)]"
|
||||
}
|
||||
|
||||
private func genericSafeType(from type: String) -> String {
|
||||
return type.replacingOccurrences(of: "!", with: "?")
|
||||
}
|
||||
|
||||
private func openNestedClosure(for method: Method) -> String {
|
||||
var fullString = ""
|
||||
for (index, parameter) in method.parameters.enumerated() {
|
||||
if parameter.isClosure && !parameter.isEscaping {
|
||||
let indents = String(repeating: "\t", count: index)
|
||||
let tries = method.isThrowing ? "try " : ""
|
||||
let awaits = method.isAsync ? "await " : ""
|
||||
|
||||
let sugarizedReturnType = method.returnType.sugarized
|
||||
let returnSignature: String
|
||||
if sugarizedReturnType.isEmpty {
|
||||
returnSignature = sugarizedReturnType
|
||||
} else {
|
||||
returnSignature = " -> \(sugarizedReturnType)"
|
||||
}
|
||||
|
||||
fullString += "\(indents)return \(tries)\(awaits)withoutActuallyEscaping(\(parameter.name), do: { (\(parameter.name): @escaping \(parameter.type))\(returnSignature) in\n"
|
||||
}
|
||||
}
|
||||
|
||||
return fullString
|
||||
}
|
||||
|
||||
private func closeNestedClosure(for parameters: [MethodParameter]) -> String {
|
||||
var fullString = ""
|
||||
for (index, parameter) in parameters.enumerated() {
|
||||
if parameter.isClosure && !parameter.isEscaping {
|
||||
let indents = String(repeating: "\t", count: index)
|
||||
fullString += "\(indents)})\n"
|
||||
}
|
||||
}
|
||||
return fullString
|
||||
}
|
||||
|
||||
private func escapeReservedKeywords(for name: String) -> String {
|
||||
Self.reservedKeywordsNotAllowedAsMethodName.contains(name) ? "`\(name)`" : name
|
||||
}
|
||||
|
||||
private func removeClosureArgumentNames(for type: String) -> String {
|
||||
type.replacingOccurrences(
|
||||
of: "_\\s+?[_a-zA-Z]\\w*?\\s*?:",
|
||||
with: "",
|
||||
options: .regularExpression
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
@dynamicMemberLookup
|
||||
public final class Reference<Value> {
|
||||
private(set) var value: Value
|
||||
|
||||
public init(value: Value) {
|
||||
self.value = value
|
||||
}
|
||||
|
||||
public subscript<T>(dynamicMember keyPath: KeyPath<Value, T>) -> T {
|
||||
value[keyPath: keyPath]
|
||||
}
|
||||
|
||||
public subscript<T>(dynamicMember keyPath: WritableKeyPath<Value, T>) -> T {
|
||||
get { value[keyPath: keyPath] }
|
||||
set { value[keyPath: keyPath] = newValue }
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public private(set) var stderrUsed = false
|
||||
|
||||
func stderrPrint(_ item: Any) {
|
||||
stderrUsed = true
|
||||
fputs("error: \(item)\n", stderr)
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
extension Templates {
|
||||
static let staticGenericParameter = "_CUCKOO$$GENERIC"
|
||||
static let typeErasureClassName = "DefaultImplCaller"
|
||||
static let mock = """
|
||||
{% for container in containers %}
|
||||
{% if debug %}
|
||||
// {{ container }}
|
||||
{% endif %}
|
||||
{{ container.unavailablePlatformsCheck }}
|
||||
{% for attribute in container.attributes %}
|
||||
{{ attribute.text }}
|
||||
{% endfor %}
|
||||
{% if container.hasParent %}
|
||||
extension {{ container.parentFullyQualifiedName }} {
|
||||
{% endif %}
|
||||
|
||||
{{ container.accessibility }} class {{ container.mockName }}{{ container.genericParameters }}: {% if container.isNSObjectProtocol %}NSObject, {% endif %}{{ container.name }}{% if container.isImplementation %}{{ container.genericArguments }}{% endif %}, {% if container.isImplementation %}Cuckoo.ClassMock{% else %}Cuckoo.ProtocolMock{% endif %} {
|
||||
{% if container.isGeneric and not container.isImplementation %}
|
||||
{{ container.accessibility }} typealias MocksType = \(typeErasureClassName){{ container.genericArguments }}
|
||||
{% else %}
|
||||
{{ container.accessibility }} typealias MocksType = {{ container.name }}{{ container.genericArguments }}
|
||||
{% endif %}
|
||||
{{ container.accessibility }} typealias Stubbing = __StubbingProxy_{{ container.name }}
|
||||
{{ container.accessibility }} typealias Verification = __VerificationProxy_{{ container.name }}
|
||||
|
||||
{{ container.accessibility }} let cuckoo_manager = Cuckoo.MockManager.preconfiguredManager ?? Cuckoo.MockManager(hasParent: {{ container.isImplementation }})
|
||||
|
||||
{% if container.isGeneric and not container.isImplementation %}
|
||||
\(Templates.typeErasure.indented())
|
||||
|
||||
private var __defaultImplStub: \(typeErasureClassName){{ container.genericArguments }}?
|
||||
|
||||
{{ container.accessibility }} func enableDefaultImplementation<\(staticGenericParameter): {{ container.name }}>(_ stub: \(staticGenericParameter)) where {{ container.genericProtocolIdentity }} {
|
||||
var mutableStub = stub
|
||||
__defaultImplStub = \(typeErasureClassName)(from: &mutableStub, keeping: mutableStub)
|
||||
cuckoo_manager.enableDefaultStubImplementation()
|
||||
}
|
||||
|
||||
{{ container.accessibility }} func enableDefaultImplementation<\(staticGenericParameter): {{ container.name }}>(mutating stub: UnsafeMutablePointer<\(staticGenericParameter)>) where {{ container.genericProtocolIdentity }} {
|
||||
__defaultImplStub = \(typeErasureClassName)(from: stub, keeping: nil)
|
||||
cuckoo_manager.enableDefaultStubImplementation()
|
||||
}
|
||||
{% else %}
|
||||
private var __defaultImplStub: {{ container.name }}{{ container.genericArguments }}?
|
||||
|
||||
{{ container.accessibility }} func enableDefaultImplementation(_ stub: {{ container.name }}{{ container.genericArguments }}) {
|
||||
__defaultImplStub = stub
|
||||
cuckoo_manager.enableDefaultStubImplementation()
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
{% for property in container.properties %}
|
||||
{{ property.unavailablePlatformsCheck }}
|
||||
{% if debug %}
|
||||
// {{property}}
|
||||
{% endif %}
|
||||
{% for attribute in property.attributes %}
|
||||
{{ attribute.text }}
|
||||
{% endfor %}
|
||||
{{ property.accessibility }}{% if container.isImplementation %} override{% endif %} var {{ property.name }}: {{ property.type }} {
|
||||
get {
|
||||
return cuckoo_manager.getter("{{ property.name }}",
|
||||
superclassCall:
|
||||
{% if container.isImplementation %}
|
||||
super.{{ property.name }}
|
||||
{% else %}
|
||||
Cuckoo.MockManager.crashOnProtocolSuperclassCall()
|
||||
{% endif %},
|
||||
defaultCall: __defaultImplStub!.{{property.name}})
|
||||
}
|
||||
{% ifnot property.isReadOnly %}
|
||||
set {
|
||||
cuckoo_manager.setter("{{ property.name }}",
|
||||
value: newValue,
|
||||
superclassCall:
|
||||
{% if container.isImplementation %}
|
||||
super.{{ property.name }} = newValue
|
||||
{% else %}
|
||||
Cuckoo.MockManager.crashOnProtocolSuperclassCall()
|
||||
{% endif %},
|
||||
defaultCall: __defaultImplStub!.{{property.name}} = newValue)
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
{% if property.hasUnavailablePlatforms %}
|
||||
#endif
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% for initializer in container.initializers %}
|
||||
{{ initializer.unavailablePlatformsCheck }}
|
||||
{% if debug %}
|
||||
// {{initializer}}
|
||||
{% endif %}
|
||||
{{ initializer.accessibility }}{% if container.isImplementation %} override{% endif %}{% if initializer.@type == "ProtocolMethod" %} required{% endif %} init({{initializer.parameterSignature}}) {
|
||||
{% if container.isImplementation %}
|
||||
super.init({{initializer.call}})
|
||||
{% endif %}
|
||||
}
|
||||
{% if initializer.hasUnavailablePlatforms %}
|
||||
#endif
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% for method in container.methods %}
|
||||
{{ method.unavailablePlatformsCheck }}
|
||||
{% if debug %}
|
||||
// {{method}}
|
||||
{% endif %}
|
||||
{% for attribute in method.attributes %}
|
||||
{{ attribute.text }}
|
||||
{% endfor %}
|
||||
{{ method.accessibility }}{% if container.isImplementation and method.isOverriding %} override{% endif %} func {{ method.name|escapeReservedKeywords }}{{ method.genericParameters }}({{ method.parameterSignature }}) {{ method.returnSignature }} {
|
||||
{{ method.self|openNestedClosure }}
|
||||
return{% if method.isThrowing %} try{% endif %}{% if method.isAsync %} await{% endif %} cuckoo_manager.call{% if method.isThrowing %}{{ method.throwType|capitalize }}{% endif %}(
|
||||
\"\"\"
|
||||
{{method.fullyQualifiedName}}
|
||||
\"\"\",
|
||||
parameters: ({{method.parameterNames}}),
|
||||
escapingParameters: ({{method.escapingParameterNames}}),
|
||||
superclassCall:
|
||||
{% if container.isImplementation %}
|
||||
{% if method.isAsync %}await {% endif %}super.{{method.name}}({{method.call}})
|
||||
{% else %}
|
||||
Cuckoo.MockManager.crashOnProtocolSuperclassCall()
|
||||
{% endif %},
|
||||
defaultCall: {% if method.isAsync %}await {% endif %}__defaultImplStub!.{{method.name}}{%if method.isOptional %}!{%endif%}({{method.call}}))
|
||||
{{ method.parameters|closeNestedClosure }}
|
||||
}
|
||||
{% if method.hasUnavailablePlatforms %}
|
||||
#endif
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
\(Templates.stubbingProxy.indented())
|
||||
|
||||
\(Templates.verificationProxy.indented())
|
||||
}
|
||||
|
||||
\(Templates.noImplStub)
|
||||
|
||||
{% if container.hasParent %}
|
||||
}
|
||||
{% endif %}
|
||||
{% if container.hasUnavailablePlatforms %}
|
||||
#endif
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
"""
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
public enum Accessibility: String {
|
||||
case Open = "source.lang.swift.accessibility.open"
|
||||
case Public = "source.lang.swift.accessibility.public"
|
||||
case Internal = "source.lang.swift.accessibility.internal"
|
||||
case Private = "source.lang.swift.accessibility.private"
|
||||
case FilePrivate = "source.lang.swift.accessibility.fileprivate"
|
||||
|
||||
public var sourceName: String {
|
||||
switch self {
|
||||
case .Open:
|
||||
fallthrough
|
||||
case .Public:
|
||||
return "public"
|
||||
case .Internal:
|
||||
return ""
|
||||
case .Private:
|
||||
return "private"
|
||||
case .FilePrivate:
|
||||
return "fileprivate"
|
||||
}
|
||||
}
|
||||
|
||||
public var isAccessible: Bool {
|
||||
return self != .Private && self != .FilePrivate
|
||||
}
|
||||
}
|
||||
|
||||
extension Accessibility: Comparable {
|
||||
/// How open is this accessibility. The higher number the more accessible.
|
||||
private var openness: Int {
|
||||
switch self {
|
||||
case .Open:
|
||||
return 4
|
||||
case .Public:
|
||||
return 3
|
||||
case .Internal:
|
||||
return 2
|
||||
case .FilePrivate:
|
||||
return 1
|
||||
case .Private:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
public static func < (lhs: Accessibility, rhs: Accessibility) -> Bool {
|
||||
return lhs.openness < rhs.openness
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public struct Attribute: Hashable {
|
||||
public enum Kind: String, Hashable {
|
||||
case objc = "source.decl.attribute.objc"
|
||||
case optional = "source.decl.attribute.optional"
|
||||
case lazy = "source.decl.attribute.lazy"
|
||||
case required = "source.decl.attribute.required"
|
||||
case override = "source.decl.attribute.override"
|
||||
case convenience = "source.decl.attribute.convenience"
|
||||
case weak = "source.decl.attribute.weak"
|
||||
case ibAction = "source.decl.attribute.ibaction"
|
||||
case ibOutlet = "source.decl.attribute.iboutlet"
|
||||
case available = "source.decl.attribute.available"
|
||||
case final = "source.decl.attribute.final"
|
||||
}
|
||||
|
||||
public var kind: Kind
|
||||
public var text: String
|
||||
|
||||
public var isSupported: Bool {
|
||||
switch (kind) {
|
||||
case .objc, .optional, .lazy, .required, .override, .convenience, .weak, .ibAction, .ibOutlet, .final:
|
||||
return false
|
||||
case .available:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public var unavailablePlatform: String? {
|
||||
guard kind == .available,
|
||||
text.hasPrefix("@available(") else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let parameters = text
|
||||
.dropFirst("@available(".count)
|
||||
.dropLast()
|
||||
.split(separator: ",")
|
||||
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
||||
|
||||
guard parameters.count >= 2,
|
||||
parameters[1] == "unavailable" else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return String(parameters[0])
|
||||
}
|
||||
}
|
||||
|
||||
extension Attribute: Token {
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let otherAttribute = other as? Attribute else { return false }
|
||||
return self.kind == otherAttribute.kind && self.text == otherAttribute.text
|
||||
}
|
||||
|
||||
public func serialize() -> [String : Any] {
|
||||
return ["text": text]
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public protocol ChildToken: Token {
|
||||
var parent: Reference<ParentToken>? { get set }
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
public struct ClassDeclaration: ContainerToken, HasAccessibility {
|
||||
public let implementation: Bool = true
|
||||
public var name: String
|
||||
public var parent: Reference<ParentToken>?
|
||||
public var accessibility: Accessibility
|
||||
public var range: CountableRange<Int>
|
||||
public var nameRange: CountableRange<Int>
|
||||
public var bodyRange: CountableRange<Int>
|
||||
public var initializers: [Initializer]
|
||||
public var children: [Token]
|
||||
public var inheritedTypes: [InheritanceDeclaration]
|
||||
public var attributes: [Attribute]
|
||||
public var genericParameters: [GenericParameter]
|
||||
public var hasNoArgInit: Bool {
|
||||
return initializers.filter { $0.parameters.isEmpty }.isEmpty
|
||||
}
|
||||
|
||||
public func replace(children tokens: [Token]) -> ClassDeclaration {
|
||||
return ClassDeclaration(
|
||||
name: self.name,
|
||||
parent: self.parent,
|
||||
accessibility: self.accessibility,
|
||||
range: self.range,
|
||||
nameRange: self.nameRange,
|
||||
bodyRange: self.bodyRange,
|
||||
initializers: self.initializers,
|
||||
children: tokens,
|
||||
inheritedTypes: self.inheritedTypes,
|
||||
attributes: self.attributes,
|
||||
genericParameters: self.genericParameters)
|
||||
}
|
||||
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? ClassDeclaration else { return false }
|
||||
return self.name == other.name
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
public struct ClassMethod: Method {
|
||||
public var name: String
|
||||
public var accessibility: Accessibility
|
||||
public var returnSignature: ReturnSignature
|
||||
public var range: CountableRange<Int>
|
||||
public var nameRange: CountableRange<Int>
|
||||
public var parameters: [MethodParameter]
|
||||
public var bodyRange: CountableRange<Int>
|
||||
public var attributes: [Attribute]
|
||||
public var genericParameters: [GenericParameter]
|
||||
public var isOptional: Bool {
|
||||
return false
|
||||
}
|
||||
public var isOverriding: Bool {
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
public protocol ContainerToken: ParentToken, ChildToken {
|
||||
var initializers: [Initializer] { get }
|
||||
var implementation: Bool { get }
|
||||
var inheritedTypes: [InheritanceDeclaration] { get }
|
||||
var genericParameters: [GenericParameter] { get }
|
||||
}
|
||||
|
||||
extension ContainerToken {
|
||||
public func serialize() -> [String : Any] {
|
||||
func withAdjustedAccessibility(token: Token & HasAccessibility) -> Token & HasAccessibility {
|
||||
// We only want to adjust tokens that are accessible and lower than the enclosing type
|
||||
guard token.accessibility.isAccessible && token.accessibility < accessibility else { return token }
|
||||
var mutableToken = token
|
||||
mutableToken.accessibility = accessibility
|
||||
return mutableToken
|
||||
}
|
||||
|
||||
let accessibilityAdjustedChildren = children.map { child -> Token in
|
||||
guard let childWithAccessibility = child as? HasAccessibility & Token else { return child }
|
||||
return withAdjustedAccessibility(token: childWithAccessibility)
|
||||
}
|
||||
|
||||
let properties = accessibilityAdjustedChildren.compactMap { $0 as? InstanceVariable }
|
||||
.filter { $0.accessibility.isAccessible }
|
||||
.map { $0.serializeWithType() }
|
||||
|
||||
let methods = accessibilityAdjustedChildren.compactMap { $0 as? Method }
|
||||
.filter { $0.accessibility.isAccessible && !$0.isInit && !$0.isDeinit }
|
||||
.map { $0.serializeWithType() }
|
||||
|
||||
let initializers = accessibilityAdjustedChildren.compactMap { $0 as? Method }
|
||||
.filter { $0.accessibility.isAccessible && $0.isInit && !$0.isDeinit }
|
||||
.map { $0.serializeWithType() }
|
||||
|
||||
let genericParametersString = genericParameters.map { $0.description }.joined(separator: ", ")
|
||||
let genericArgumentsString = genericParameters.map { $0.name }.joined(separator: ", ")
|
||||
let genericProtocolIdentity = genericParameters.map { "\(Templates.staticGenericParameter).\($0.name) == \($0.name)" }.joined(separator: ", ")
|
||||
let isGeneric = !genericParameters.isEmpty
|
||||
|
||||
return [
|
||||
"name": name,
|
||||
"accessibility": accessibility.sourceName,
|
||||
"isAccessible": accessibility.isAccessible,
|
||||
"hasParent": parent != nil,
|
||||
"parentFullyQualifiedName": parent?.fullyQualifiedName ?? "",
|
||||
"children": accessibilityAdjustedChildren.map { $0.serializeWithType() },
|
||||
"properties": properties,
|
||||
"methods": methods,
|
||||
"initializers": implementation ? [] : initializers,
|
||||
"isImplementation": implementation,
|
||||
"mockName": "Mock\(name)",
|
||||
"inheritedTypes": inheritedTypes,
|
||||
"attributes": attributes.filter { $0.isSupported },
|
||||
"hasUnavailablePlatforms": hasUnavailablePlatforms,
|
||||
"unavailablePlatformsCheck": unavailablePlatformsCheck,
|
||||
"isGeneric": isGeneric,
|
||||
"genericParameters": isGeneric ? "<\(genericParametersString)>" : "",
|
||||
"genericArguments": isGeneric ? "<\(genericArgumentsString)>" : "",
|
||||
"genericProtocolIdentity": genericProtocolIdentity,
|
||||
"isNSObjectProtocol": (self as? ProtocolDeclaration)?.isNSObjectProtocol ?? false
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
public struct ExtensionDeclaration: ParentToken {
|
||||
// TODO Implement support for extensions
|
||||
public let name: String
|
||||
public var accessibility: Accessibility
|
||||
public let range: CountableRange<Int>
|
||||
public let nameRange: CountableRange<Int>
|
||||
public let bodyRange: CountableRange<Int>
|
||||
public var attributes: [Attribute]
|
||||
public let children: [Token]
|
||||
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? ExtensionDeclaration else { return false }
|
||||
return self.range == other.range
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
import SourceKittenFramework
|
||||
|
||||
public struct FileRepresentation {
|
||||
public let sourceFile: File
|
||||
public let declarations: [Token]
|
||||
|
||||
public init(sourceFile: File, declarations: [Token]) {
|
||||
self.sourceFile = sourceFile
|
||||
self.declarations = declarations
|
||||
}
|
||||
}
|
||||
|
||||
public extension FileRepresentation {
|
||||
func mergeInheritance(with files: [FileRepresentation]) -> FileRepresentation {
|
||||
let tokens = self.declarations.reduce([Token]()) { list, token in
|
||||
let mergeToken = token.mergeInheritance(with: files)
|
||||
return list + [mergeToken]
|
||||
}
|
||||
|
||||
return FileRepresentation(sourceFile: self.sourceFile, declarations: tokens)
|
||||
}
|
||||
|
||||
func inheritNSObject(subjects: [ProtocolDeclaration]) -> FileRepresentation {
|
||||
FileRepresentation(sourceFile: self.sourceFile, declarations: self.declarations.map { $0.inheritNSObject(subjects: subjects) })
|
||||
}
|
||||
}
|
||||
|
||||
extension Token {
|
||||
func mergeInheritance(with files: [FileRepresentation]) -> Token {
|
||||
guard let typeToken = self as? ContainerToken else {
|
||||
return self
|
||||
}
|
||||
let inheritedRepresentations: [Token] = typeToken.inheritedTypes
|
||||
.compactMap { Self.findToken(forClassOrProtocol: $0.name, in: files) }
|
||||
.compactMap { $0.mergeInheritance(with: files) }
|
||||
|
||||
// Merge super declarations
|
||||
let mergedTokens = inheritedRepresentations.filter { $0.isClassOrProtocolDeclaration }
|
||||
.map { $0 as! ContainerToken }
|
||||
.flatMap { $0.children }
|
||||
.reduce(typeToken.children) { tokens, inheritedToken in
|
||||
if tokens.contains(where: { $0 == inheritedToken }) {
|
||||
return tokens
|
||||
}
|
||||
return tokens + [inheritedToken]
|
||||
}
|
||||
|
||||
switch typeToken {
|
||||
case let classToken as ClassDeclaration:
|
||||
return classToken.replace(children: mergedTokens)
|
||||
case let protocolToken as ProtocolDeclaration:
|
||||
return protocolToken.replace(children: mergedTokens)
|
||||
default:
|
||||
return typeToken
|
||||
}
|
||||
}
|
||||
|
||||
func inheritNSObject(subjects: [ProtocolDeclaration]) -> Token {
|
||||
guard let protocolToken = self as? ProtocolDeclaration else {
|
||||
return self
|
||||
}
|
||||
return subjects.contains { $0.name == protocolToken.name } ? protocolToken.replace(isNSObjectProtocol: true) : self
|
||||
}
|
||||
|
||||
static func findToken(forClassOrProtocol name: String, in files: [FileRepresentation]) -> Token? {
|
||||
return files.flatMap { $0.declarations }
|
||||
.filter { $0.isClassOrProtocolDeclaration }
|
||||
.map { $0 as! ContainerToken }
|
||||
.first { $0.name == name }
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public struct GenericParameter: Token {
|
||||
public let name: String
|
||||
public let range: CountableRange<Int>
|
||||
public let inheritedType: InheritanceDeclaration?
|
||||
|
||||
public var description: String {
|
||||
let hasInheritedType = inheritedType != nil
|
||||
return "\(name)\(hasInheritedType ? ": " : "")\(inheritedType?.name ?? "")"
|
||||
}
|
||||
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? GenericParameter else { return false }
|
||||
return self.name == other.name && self.range == other.range && self.inheritedType?.name == other.inheritedType?.name
|
||||
}
|
||||
|
||||
public func serialize() -> [String : Any] {
|
||||
return [
|
||||
"name": name,
|
||||
"inheritedType": inheritedType,
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public protocol HasAccessibility {
|
||||
var accessibility: Accessibility { get set }
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public protocol HasAttributes {
|
||||
var attributes: [Attribute] { get }
|
||||
}
|
||||
|
||||
extension HasAttributes {
|
||||
private var unavailablePlatforms: [String] {
|
||||
return attributes.lazy.compactMap { $0.unavailablePlatform }
|
||||
}
|
||||
|
||||
var hasUnavailablePlatforms: Bool {
|
||||
return !unavailablePlatforms.isEmpty
|
||||
}
|
||||
|
||||
var unavailablePlatformsCheck: String {
|
||||
return hasUnavailablePlatforms ? "#if !os(\(unavailablePlatforms.joined(separator: ") && !os(")))" : ""
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
public struct Import: Token {
|
||||
public enum Importee: CustomStringConvertible {
|
||||
case library(name: String)
|
||||
case component(componentType: String?, library: String, name: String)
|
||||
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .library(let name):
|
||||
return name
|
||||
case .component(let componentType, let library, let name):
|
||||
return [componentType, "\(library).\(name)"].compactMap { $0 }.joined(separator: " ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public let range: CountableRange<Int>
|
||||
public let importee: Importee
|
||||
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? Import, self.range == other.range else { return false }
|
||||
switch (self.importee, other.importee) {
|
||||
case (.library(let lhsName), .library(let rhsName)):
|
||||
return lhsName == rhsName
|
||||
case (.component(let lhsImportType, let lhsLibrary, let lhsName), .component(let rhsImportType, let rhsLibrary, let rhsName)):
|
||||
return lhsImportType == rhsImportType && lhsLibrary == rhsLibrary && lhsName == rhsName
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
public struct InheritanceDeclaration: Token {
|
||||
public static let empty = InheritanceDeclaration(name: Tokenizer.nameNotSet)
|
||||
public let name: String
|
||||
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? InheritanceDeclaration else { return false }
|
||||
return self.name == other.name
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
public struct Initializer: Method, HasAccessibility {
|
||||
public var name: String
|
||||
public var accessibility: Accessibility
|
||||
public var returnType: WrappableType
|
||||
public var returnSignature: ReturnSignature
|
||||
public var range: CountableRange<Int>
|
||||
public var nameRange: CountableRange<Int>
|
||||
public var parameters: [MethodParameter]
|
||||
public var isOverriding: Bool
|
||||
public var required: Bool
|
||||
public var attributes: [Attribute]
|
||||
public var genericParameters: [GenericParameter]
|
||||
|
||||
public var isOptional: Bool {
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
public struct InstanceVariable: Token, HasAccessibility, HasAttributes {
|
||||
public var name: String
|
||||
public var type: WrappableType
|
||||
public var accessibility: Accessibility
|
||||
public var setterAccessibility: Accessibility?
|
||||
public var range: CountableRange<Int>
|
||||
public var nameRange: CountableRange<Int>
|
||||
public var overriding: Bool
|
||||
public var attributes: [Attribute]
|
||||
|
||||
public var readOnly: Bool {
|
||||
if let setterAccessibility = setterAccessibility {
|
||||
return !setterAccessibility.isAccessible
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? InstanceVariable else { return false }
|
||||
return self.name == other.name
|
||||
}
|
||||
|
||||
public func serialize() -> [String : Any] {
|
||||
let readOnlyString = readOnly ? "ReadOnly" : ""
|
||||
let optionalString = type.isOptional && !readOnly ? "Optional" : ""
|
||||
|
||||
return [
|
||||
"name": name,
|
||||
"type": type.sugarized,
|
||||
"nonOptionalType": type.unoptionaled.sugarized,
|
||||
"accessibility": accessibility.sourceName,
|
||||
"isReadOnly": readOnly,
|
||||
"stubType": (overriding ? "Class" : "Protocol") + "ToBeStubbed\(readOnlyString)\(optionalString)Property",
|
||||
"verifyType": "Verify\(readOnlyString)\(optionalString)Property",
|
||||
"attributes": attributes.filter { $0.isSupported },
|
||||
"hasUnavailablePlatforms": hasUnavailablePlatforms,
|
||||
"unavailablePlatformsCheck": unavailablePlatformsCheck,
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
public enum Key: String {
|
||||
case Substructure = "key.substructure"
|
||||
case Kind = "key.kind"
|
||||
case Accessibility = "key.accessibility"
|
||||
case SetterAccessibility = "key.setter_accessibility"
|
||||
case Name = "key.name"
|
||||
case TypeName = "key.typename"
|
||||
case InheritedTypes = "key.inheritedtypes"
|
||||
case Attributes = "key.attributes"
|
||||
case Attribute = "key.attribute"
|
||||
|
||||
case Length = "key.length"
|
||||
case Offset = "key.offset"
|
||||
|
||||
case NameLength = "key.namelength"
|
||||
case NameOffset = "key.nameoffset"
|
||||
|
||||
case BodyLength = "key.bodylength"
|
||||
case BodyOffset = "key.bodyoffset"
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
public enum Kinds: String {
|
||||
case ProtocolDeclaration = "source.lang.swift.decl.protocol"
|
||||
case InstanceMethod = "source.lang.swift.decl.function.method.instance"
|
||||
case MethodParameter = "source.lang.swift.decl.var.parameter"
|
||||
case ClassDeclaration = "source.lang.swift.decl.class"
|
||||
case StructDeclaration = "source.lang.swift.decl.struct"
|
||||
case ExtensionDeclaration = "source.lang.swift.decl.extension"
|
||||
case InstanceVariable = "source.lang.swift.decl.var.instance"
|
||||
case GenericParameter = "source.lang.swift.decl.generic_type_param"
|
||||
case AssociatedType = "source.lang.swift.decl.associatedtype"
|
||||
case Optional = "source.decl.attribute.optional"
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public protocol Method: Token, HasAccessibility, HasAttributes {
|
||||
var name: String { get }
|
||||
var returnSignature: ReturnSignature { get }
|
||||
var range: CountableRange<Int> { get }
|
||||
var nameRange: CountableRange<Int> { get }
|
||||
var parameters: [MethodParameter] { get }
|
||||
var isOptional: Bool { get }
|
||||
var isOverriding: Bool { get }
|
||||
var hasClosureParams: Bool { get }
|
||||
var hasOptionalParams: Bool { get }
|
||||
var genericParameters: [GenericParameter] { get }
|
||||
}
|
||||
|
||||
public extension Method {
|
||||
var rawName: String {
|
||||
return name.takeUntil(occurence: "(") ?? ""
|
||||
}
|
||||
|
||||
var isInit: Bool {
|
||||
return rawName == "init"
|
||||
}
|
||||
|
||||
var isDeinit: Bool {
|
||||
return rawName == "deinit"
|
||||
}
|
||||
|
||||
var fullyQualifiedName: String {
|
||||
let parameterTypes = parameters.map { ($0.isInout ? "inout " : "") + $0.type.sugarized }
|
||||
let nameParts = name.components(separatedBy: ":")
|
||||
let lastNamePart = nameParts.last ?? ""
|
||||
|
||||
let returnSignatureDescription = returnSignature.description
|
||||
let returnSignatureString = returnSignatureDescription.isEmpty ? "" : " \(returnSignatureDescription)"
|
||||
|
||||
return zip(nameParts.dropLast(), parameterTypes)
|
||||
.map { $0 + ": " + $1 }
|
||||
.joined(separator: ", ") + lastNamePart + returnSignatureString
|
||||
}
|
||||
|
||||
var isAsync: Bool {
|
||||
return returnSignature.isAsync
|
||||
}
|
||||
|
||||
var isThrowing: Bool {
|
||||
guard let throwType = returnSignature.throwType else { return false }
|
||||
return throwType.isThrowing || throwType.isRethrowing
|
||||
}
|
||||
|
||||
var returnType: WrappableType {
|
||||
return returnSignature.returnType
|
||||
}
|
||||
|
||||
var hasClosureParams: Bool {
|
||||
return parameters.contains { $0.isClosure }
|
||||
}
|
||||
|
||||
var hasOptionalParams: Bool {
|
||||
return parameters.contains { $0.isOptional }
|
||||
}
|
||||
|
||||
func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? Method else { return false }
|
||||
return self.name == other.name && self.parameters == other.parameters && self.returnType == other.returnType
|
||||
}
|
||||
|
||||
func serialize() -> [String : Any] {
|
||||
let call = parameters.map {
|
||||
let referencedName = "\($0.isInout ? "&" : "")\($0.name)\($0.isAutoClosure ? "()" : "")"
|
||||
if let label = $0.label {
|
||||
return "\(label): \(referencedName)"
|
||||
} else {
|
||||
return referencedName
|
||||
}
|
||||
}.joined(separator: ", ")
|
||||
|
||||
let stubFunctionPrefix = isOverriding ? "Class" : "Protocol"
|
||||
let returnString = returnType.sugarized == "Void" ? "NoReturn" : ""
|
||||
let throwingString = isThrowing ? "Throwing" : ""
|
||||
let stubFunction = "Cuckoo.\(stubFunctionPrefix)Stub\(returnString)\(throwingString)Function"
|
||||
|
||||
let escapingParameterNames = parameters.map { parameter in
|
||||
if parameter.isClosure && !parameter.isEscaping {
|
||||
let parameterCount = parameter.closureParamCount
|
||||
let parameterSignature = parameterCount > 0 ? (1...parameterCount).map { _ in "_" }.joined(separator: ", ") : "()"
|
||||
|
||||
// FIXME: Instead of parsing the closure return type here, Tokenizer should do it and pass the information in a data structure
|
||||
let returnSignature: String
|
||||
let closureReturnType = extractClosureReturnType(parameter: parameter.type.sugarized)
|
||||
if let closureReturnType = closureReturnType, !closureReturnType.isEmpty && closureReturnType != "Void" {
|
||||
returnSignature = " -> " + closureReturnType
|
||||
} else {
|
||||
returnSignature = ""
|
||||
}
|
||||
return "{ \(parameterSignature)\(returnSignature) in fatalError(\"This is a stub! It's not supposed to be called!\") }"
|
||||
} else {
|
||||
return parameter.name
|
||||
}
|
||||
}.joined(separator: ", ")
|
||||
|
||||
let genericParametersString = genericParameters.map { $0.description }.joined(separator: ", ")
|
||||
let isGeneric = !genericParameters.isEmpty
|
||||
|
||||
return [
|
||||
"self": self,
|
||||
"name": rawName,
|
||||
"accessibility": accessibility.sourceName,
|
||||
"returnSignature": returnSignature.description,
|
||||
"parameters": parameters,
|
||||
"parameterNames": parameters.map { $0.name }.joined(separator: ", "),
|
||||
"escapingParameterNames": escapingParameterNames,
|
||||
"isInit": isInit,
|
||||
"returnType": returnType.explicitOptionalOnly.sugarized,
|
||||
"isAsync": isAsync,
|
||||
"isThrowing": isThrowing,
|
||||
"throwType": returnSignature.throwType?.description ?? "",
|
||||
"fullyQualifiedName": fullyQualifiedName,
|
||||
"call": call,
|
||||
"isOverriding": isOverriding,
|
||||
"parameterSignature": parameters.map { "\($0.labelAndName): \($0.isInout ? "inout " : "")\($0.type)" }.joined(separator: ", "),
|
||||
"parameterSignatureWithoutNames": parameters.map { "\($0.name): \($0.type)" }.joined(separator: ", "),
|
||||
"argumentSignature": parameters.map { $0.type.description }.joined(separator: ", "),
|
||||
"stubFunction": stubFunction,
|
||||
"inputTypes": parameters.map { $0.typeWithoutAttributes }.joined(separator: ", "),
|
||||
"isOptional": isOptional,
|
||||
"hasClosureParams": hasClosureParams,
|
||||
"hasOptionalParams": hasOptionalParams,
|
||||
"attributes": attributes.filter { $0.isSupported },
|
||||
"hasUnavailablePlatforms": hasUnavailablePlatforms,
|
||||
"unavailablePlatformsCheck": unavailablePlatformsCheck,
|
||||
"genericParameters": isGeneric ? "<\(genericParametersString)>" : "",
|
||||
]
|
||||
}
|
||||
|
||||
private func extractClosureReturnType(parameter: String) -> String? {
|
||||
var parenLevel = 0
|
||||
for i in 0..<parameter.count {
|
||||
let index = parameter.index(parameter.startIndex, offsetBy: i)
|
||||
let character = parameter[index]
|
||||
if character == "(" {
|
||||
parenLevel += 1
|
||||
} else if character == ")" {
|
||||
parenLevel -= 1
|
||||
if parenLevel == 0 {
|
||||
let returnSignature = String(parameter[parameter.index(after: index)..<parameter.endIndex])
|
||||
let regex = try! NSRegularExpression(pattern: "\\s*->\\s*(.*)\\s*")
|
||||
guard let result = regex.matches(in: returnSignature, range: NSRange(location: 0, length: returnSignature.count)).first else { return nil }
|
||||
return returnSignature[result.range(at: 1)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
public struct MethodParameter: Token, Equatable {
|
||||
public var label: String?
|
||||
public var name: String
|
||||
public var type: WrappableType
|
||||
public var range: CountableRange<Int>
|
||||
public var nameRange: CountableRange<Int>?
|
||||
public var isInout: Bool
|
||||
|
||||
public var labelAndName: String {
|
||||
if let label = label {
|
||||
return label != name ? "\(label) \(name)" : name
|
||||
} else {
|
||||
return "_ \(name)"
|
||||
}
|
||||
}
|
||||
|
||||
public var typeWithoutAttributes: String {
|
||||
return type.withoutAttributes.sugarized.trimmed
|
||||
}
|
||||
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? MethodParameter else { return false }
|
||||
return label == other.label && type == other.type
|
||||
}
|
||||
|
||||
public var isClosure: Bool {
|
||||
return typeWithoutAttributes.hasPrefix("(") && typeWithoutAttributes.range(of: "->") != nil
|
||||
}
|
||||
|
||||
public var isAutoClosure: Bool {
|
||||
type.containsAttribute(named: "@autoclosure")
|
||||
}
|
||||
|
||||
public var isOptional: Bool {
|
||||
return type.isOptional
|
||||
}
|
||||
|
||||
public var closureParamCount: Int {
|
||||
// make sure that the parameter is a closure and that it's not just an empty `() -> ...` closure
|
||||
guard isClosure && !"^\\s*\\(\\s*\\)".regexMatches(typeWithoutAttributes) else { return 0 }
|
||||
|
||||
var parenLevel = 0
|
||||
var parameterCount = 1
|
||||
for character in typeWithoutAttributes {
|
||||
switch character {
|
||||
case "(", "<":
|
||||
parenLevel += 1
|
||||
case ")", ">":
|
||||
parenLevel -= 1
|
||||
case ",":
|
||||
parameterCount += parenLevel == 1 ? 1 : 0
|
||||
default:
|
||||
break
|
||||
}
|
||||
if parenLevel == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return parameterCount
|
||||
}
|
||||
|
||||
public var isEscaping: Bool {
|
||||
return isClosure && (type.containsAttribute(named: "@escaping") || type.isOptional)
|
||||
}
|
||||
|
||||
public func serialize() -> [String : Any] {
|
||||
return [
|
||||
"label": label ?? "",
|
||||
"name": name,
|
||||
"type": type,
|
||||
"labelAndName": labelAndName,
|
||||
"typeWithoutAttributes": typeWithoutAttributes,
|
||||
"isClosure": isClosure,
|
||||
"isOptional": isOptional,
|
||||
"isEscaping": isEscaping
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
public func ==(lhs: MethodParameter, rhs: MethodParameter) -> Bool {
|
||||
return lhs.isEqual(to: rhs)
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public protocol ParentToken: Token, HasAccessibility, HasAttributes {
|
||||
var name: String { get }
|
||||
var range: CountableRange<Int> { get }
|
||||
var nameRange: CountableRange<Int> { get }
|
||||
var bodyRange: CountableRange<Int> { get }
|
||||
var children: [Token] { get }
|
||||
}
|
||||
|
||||
extension ParentToken {
|
||||
|
||||
var fullyQualifiedName: String {
|
||||
var names = [name]
|
||||
var parent: ParentToken? = (self as? ChildToken)?.parent?.value
|
||||
while let p = parent {
|
||||
names.insert(p.name, at: 0)
|
||||
parent = (p as? ChildToken)?.parent?.value
|
||||
}
|
||||
return names.joined(separator: ".")
|
||||
}
|
||||
|
||||
var areAllHierarchiesAccessible: Bool {
|
||||
guard accessibility.isAccessible else { return false }
|
||||
var parent: ParentToken? = (self as? ChildToken)?.parent?.value
|
||||
while let p = parent {
|
||||
guard p.accessibility.isAccessible else { return false }
|
||||
parent = (p as? ChildToken)?.parent?.value
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func adoptAllYoungerGenerations() -> [ParentToken] {
|
||||
let parentReference: Reference<ParentToken> = Reference(value: self)
|
||||
return children
|
||||
.compactMap { child -> ParentToken? in
|
||||
guard var c = child as? ContainerToken else { return nil }
|
||||
c.parent = parentReference
|
||||
return c
|
||||
}
|
||||
.flatMap { [$0] + $0.adoptAllYoungerGenerations() }
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
public struct ProtocolDeclaration: ContainerToken, HasAccessibility {
|
||||
public let implementation: Bool = false
|
||||
public var name: String
|
||||
public var parent: Reference<ParentToken>?
|
||||
public var accessibility: Accessibility
|
||||
public var range: CountableRange<Int>
|
||||
public var nameRange: CountableRange<Int>
|
||||
public var bodyRange: CountableRange<Int>
|
||||
public var initializers: [Initializer]
|
||||
public var children: [Token]
|
||||
public var inheritedTypes: [InheritanceDeclaration]
|
||||
public var attributes: [Attribute]
|
||||
public var genericParameters: [GenericParameter]
|
||||
public var isNSObjectProtocol: Bool
|
||||
|
||||
public func replace(children tokens: [Token]) -> ProtocolDeclaration {
|
||||
return ProtocolDeclaration(
|
||||
name: self.name,
|
||||
parent: self.parent,
|
||||
accessibility: self.accessibility,
|
||||
range: self.range,
|
||||
nameRange: self.nameRange,
|
||||
bodyRange: self.bodyRange,
|
||||
initializers: self.initializers,
|
||||
children: tokens,
|
||||
inheritedTypes: self.inheritedTypes,
|
||||
attributes: self.attributes,
|
||||
genericParameters: self.genericParameters,
|
||||
isNSObjectProtocol: self.isNSObjectProtocol
|
||||
)
|
||||
}
|
||||
|
||||
public func replace(isNSObjectProtocol: Bool) -> ProtocolDeclaration {
|
||||
ProtocolDeclaration(
|
||||
name: self.name,
|
||||
parent: self.parent,
|
||||
accessibility: self.accessibility,
|
||||
range: self.range,
|
||||
nameRange: self.nameRange,
|
||||
bodyRange: self.bodyRange,
|
||||
initializers: self.initializers,
|
||||
children: self.children,
|
||||
inheritedTypes: self.inheritedTypes,
|
||||
attributes: self.attributes,
|
||||
genericParameters: self.genericParameters,
|
||||
isNSObjectProtocol: isNSObjectProtocol
|
||||
)
|
||||
}
|
||||
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? ProtocolDeclaration else { return false }
|
||||
return self.name == other.name
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
public struct ProtocolMethod: Method {
|
||||
public var name: String
|
||||
public var accessibility: Accessibility
|
||||
public var returnSignature: ReturnSignature
|
||||
public var range: CountableRange<Int>
|
||||
public var nameRange: CountableRange<Int>
|
||||
public var parameters: [MethodParameter]
|
||||
public var attributes: [Attribute]
|
||||
public var genericParameters: [GenericParameter]
|
||||
|
||||
public var isOptional: Bool {
|
||||
return attributes.map { $0.kind }.contains(.optional)
|
||||
}
|
||||
public var isOverriding: Bool {
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public struct ReturnSignature {
|
||||
public var isAsync: Bool
|
||||
public var throwType: ThrowType?
|
||||
public var returnType: WrappableType
|
||||
public var whereConstraints: [String]
|
||||
|
||||
public init(isAsync: Bool, throwString: String?, returnType: WrappableType, whereConstraints: [String]) {
|
||||
self.isAsync = isAsync
|
||||
if let throwString = throwString {
|
||||
throwType = ThrowType(string: throwString)
|
||||
} else {
|
||||
throwType = nil
|
||||
}
|
||||
self.returnType = returnType
|
||||
self.whereConstraints = whereConstraints
|
||||
}
|
||||
}
|
||||
|
||||
extension ReturnSignature: CustomStringConvertible {
|
||||
public var description: String {
|
||||
let asyncString = isAsync ? "async" : nil
|
||||
let trimmedReturnType = returnType.explicitOptionalOnly.sugarized.trimmed
|
||||
let returnString = trimmedReturnType.isEmpty || trimmedReturnType == "Void" ? nil : "-> \(returnType)"
|
||||
let whereString = whereConstraints.isEmpty ? nil : "where \(whereConstraints.joined(separator: ", "))"
|
||||
return [asyncString, throwType?.description, returnString, whereString].compactMap { $0 }.joined(separator: " ")
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public struct StructDeclaration: ParentToken {
|
||||
// NOTE: Purely for supporting nested classes, could be any generic parent (like extensions)
|
||||
public let name: String
|
||||
public var accessibility: Accessibility
|
||||
public let range: CountableRange<Int>
|
||||
public let nameRange: CountableRange<Int>
|
||||
public let bodyRange: CountableRange<Int>
|
||||
public var attributes: [Attribute]
|
||||
public let children: [Token]
|
||||
|
||||
public func isEqual(to other: Token) -> Bool {
|
||||
guard let other = other as? StructDeclaration else { return false }
|
||||
return self.name == other.name
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
public enum ThrowType: CustomStringConvertible {
|
||||
case throwing
|
||||
case rethrowing
|
||||
|
||||
public init?(string: String) {
|
||||
if string.trimmed.hasPrefix("throws") {
|
||||
self = .throwing
|
||||
} else if string.trimmed.hasPrefix("rethrows") {
|
||||
self = .rethrowing
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public var isThrowing: Bool {
|
||||
return self == .throwing
|
||||
}
|
||||
|
||||
public var isRethrowing: Bool {
|
||||
return self == .rethrowing
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .throwing:
|
||||
return "throws"
|
||||
case .rethrowing:
|
||||
return "rethrows"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
public protocol Token {
|
||||
func isEqual(to other: Token) -> Bool
|
||||
|
||||
func serialize() -> [String: Any]
|
||||
}
|
||||
|
||||
public func ==(rhs: Token, lhs: Token) -> Bool {
|
||||
return rhs.isEqual(to: lhs)
|
||||
}
|
||||
|
||||
public extension Token {
|
||||
func serialize() -> [String: Any] {
|
||||
return [:]
|
||||
}
|
||||
|
||||
func serializeWithType() -> [String: Any] {
|
||||
var serialized = serialize()
|
||||
serialized["@type"] = "\(type(of: self))"
|
||||
return serialized
|
||||
}
|
||||
|
||||
var isClassOrProtocolDeclaration: Bool {
|
||||
return self is ProtocolDeclaration || self is ClassDeclaration
|
||||
}
|
||||
|
||||
var isInheritanceDeclaration: Bool {
|
||||
return self is InheritanceDeclaration
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
import Foundation
|
||||
import FileKit
|
||||
|
||||
public enum CuckooGeneratorError: Error {
|
||||
enum CuckooGeneratorError: Error {
|
||||
case ioError(FileKitError)
|
||||
case unknownError(Error)
|
||||
case stderrUsed
|
||||
|
||||
public var description: String {
|
||||
var description: String {
|
||||
switch self {
|
||||
case .ioError(let error):
|
||||
return error.description
|
|
@ -1,38 +1,40 @@
|
|||
import Foundation
|
||||
import Commandant
|
||||
import Result
|
||||
import SourceKittenFramework
|
||||
import FileKit
|
||||
|
||||
private func curry<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, R>
|
||||
(_ f: @escaping (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R)
|
||||
-> (P1) -> (P2) -> (P3) -> (P4) -> (P5) -> (P6) -> (P7) -> (P8) -> (P9) -> (P10) -> (P11) -> (P12) -> R {
|
||||
return { p1 in { p2 in { p3 in { p4 in { p5 in { p6 in { p7 in { p8 in { p9 in { p10 in { p11 in { p12 in
|
||||
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)
|
||||
} } } } } } } } } } } }
|
||||
}
|
||||
struct GenerateMocksCommand: CommandProtocol {
|
||||
typealias TokenFilter = (Token) -> Bool
|
||||
|
||||
public struct GenerateMocksCommand: CommandProtocol {
|
||||
let verb = "generate"
|
||||
let function = "Generates mock files"
|
||||
|
||||
public let verb = "generate"
|
||||
public let function = "Generates mock files"
|
||||
|
||||
public func run(_ options: Options) -> Result<Void, CuckooGeneratorError> {
|
||||
let getFullPathSortedArray: ([String]) -> [String] = { stringArray in
|
||||
Array(Set(stringArray.map { Path($0).standardRawValue })).sorted()
|
||||
}
|
||||
func run(_ options: Options) -> Result<Void, CuckooGeneratorError> {
|
||||
let inputPathValues: [String]
|
||||
if options.globEnabled {
|
||||
inputPathValues = getFullPathSortedArray(options.files.flatMap { Glob(pattern: $0).paths })
|
||||
if options.isGlobEnabled {
|
||||
inputPathValues = options.files.flatMap { Glob(pattern: $0).paths }
|
||||
} else {
|
||||
inputPathValues = getFullPathSortedArray(options.files)
|
||||
inputPathValues = options.files
|
||||
}
|
||||
let inputFiles = inputPathValues.map { File(path: $0) }.compactMap { $0 }
|
||||
let tokens = inputFiles.map { Tokenizer(sourceFile: $0, debugMode: options.debugMode).tokenize() }
|
||||
let tokensWithInheritance = options.noInheritance ? tokens : inheritNSObject(mergeInheritance(tokens))
|
||||
let sortedInputPathValues = Array(Set(inputPathValues.map { Path($0).standardRawValue })).sorted()
|
||||
|
||||
let inputFiles = sortedInputPathValues
|
||||
.map { Path($0) }
|
||||
.filter { $0.exists }
|
||||
.map(TextFile.init(path:))
|
||||
|
||||
// try! Crawler.crawl(url: URL(string: "www.google.com")!)
|
||||
// return .success(())
|
||||
|
||||
let files: [FileRepresentation] = inputFiles.compactMap { file in
|
||||
guard let crawler = try? Crawler.crawl(url: file.path.url) else { return nil }
|
||||
return FileRepresentation(file: file, imports: crawler.imports, tokens: crawler.tokens)
|
||||
}
|
||||
let flatMappedFiles = files.map { $0.flatMappingMemberContainers() }
|
||||
let finalFiles = options.noInheritance ? flatMappedFiles : inheritNSObject(mergingInheritance(flatMappedFiles))
|
||||
|
||||
// filter classes/protocols based on the settings passed to the generator
|
||||
var typeFilters = [] as [(Token) -> Bool]
|
||||
var typeFilters: [TokenFilter] = []
|
||||
if options.noClassMocking {
|
||||
typeFilters.append(ignoreClasses)
|
||||
}
|
||||
|
@ -40,106 +42,105 @@ public struct GenerateMocksCommand: CommandProtocol {
|
|||
typeFilters.append(keepMatching(pattern: options.regex))
|
||||
}
|
||||
if !options.exclude.isEmpty {
|
||||
typeFilters.append(ignoreIfExists(in: options.exclude))
|
||||
typeFilters.append(ignoreExcluded(in: options.exclude))
|
||||
}
|
||||
let parsedFiles = removeTypes(from: tokensWithInheritance, using: typeFilters)
|
||||
let parsedFiles = removeTypes(from: finalFiles, using: typeFilters)
|
||||
let mockableFiles = parsedFiles.map { $0.replacing(tokens: $0.tokens.filter { $0.isMockable }) }
|
||||
|
||||
// generating headers and mocks
|
||||
let headers = parsedFiles.map { options.noHeader ? "" : FileHeaderHandler.getHeader(of: $0, includeTimestamp: !options.noTimestamp) }
|
||||
let imports = parsedFiles.map { FileHeaderHandler.getImports(of: $0, testableFrameworks: options.testableFrameworks) }
|
||||
let mocks = parsedFiles.map { try! Generator(file: $0).generate(debug: options.debugMode) }
|
||||
|
||||
let mergedFiles = zip(zip(headers, imports), mocks).map { $0.0 + $0.1 + $1 }
|
||||
let outputPath = Path(options.output)
|
||||
let timestamp = options.noTimestamp || options.noHeader ? nil : Date().description
|
||||
let generatedFileContents = try! mockableFiles.map { file in
|
||||
[
|
||||
options.noHeader ? nil : FileHeaderHandler.header(for: file, timestamp: timestamp),
|
||||
FileHeaderHandler.imports(for: file, testableFrameworks: options.testableFrameworks),
|
||||
try Generator.generate(tokens: file.tokens, debug: options.isDebug),
|
||||
]
|
||||
.compactMap { $0 }
|
||||
.joined(separator: "\n\n")
|
||||
}
|
||||
|
||||
do {
|
||||
let outputPath = Path(options.output)
|
||||
if outputPath.isDirectory {
|
||||
let inputPaths = inputFiles.compactMap { $0.path }.map { Path($0) }
|
||||
for (inputPath, outputText) in zip(inputPaths, mergedFiles) {
|
||||
let inputPaths = inputFiles.map { $0.path }
|
||||
for (inputPath, outputText) in zip(inputPaths, generatedFileContents) {
|
||||
let fileName = options.filePrefix + inputPath.fileName
|
||||
let outputFile = TextFile(path: outputPath + fileName)
|
||||
try outputText |> outputFile
|
||||
try outputFile.write(outputText)
|
||||
}
|
||||
} else {
|
||||
let outputFile = TextFile(path: outputPath)
|
||||
try mergedFiles.joined(separator: "\n") |> outputFile
|
||||
try outputFile.write(generatedFileContents.joined(separator: "\n\n"))
|
||||
}
|
||||
} catch let error as FileKitError {
|
||||
return .failure(.ioError(error))
|
||||
} catch let error {
|
||||
} catch {
|
||||
return .failure(.unknownError(error))
|
||||
}
|
||||
|
||||
return stderrUsed ? .failure(.stderrUsed) : .success(())
|
||||
return .success(())
|
||||
}
|
||||
|
||||
private func mergeInheritance(_ filesRepresentation: [FileRepresentation]) -> [FileRepresentation] {
|
||||
return filesRepresentation.compactMap { $0.mergeInheritance(with: filesRepresentation) }
|
||||
private func mergingInheritance(_ filesRepresentation: [FileRepresentation]) -> [FileRepresentation] {
|
||||
return filesRepresentation.compactMap { $0.mergingInheritance(with: filesRepresentation) }
|
||||
}
|
||||
|
||||
private func inheritNSObject(_ filesRepresentation: [FileRepresentation]) -> [FileRepresentation] {
|
||||
func containsRecursively(name: String) -> Bool {
|
||||
if let protocolDeclaration = protocolDeclarationDictionary[name] {
|
||||
let collapsedInheritedTypesName = protocolDeclaration
|
||||
.inheritedTypes
|
||||
.map({ $0.name.components(separatedBy: "&") })
|
||||
.joined()
|
||||
.map({ $0.trimmingCharacters(in: .whitespaces) })
|
||||
guard let protocolDeclaration = protocolDeclarationDictionary[name] else { return false }
|
||||
let collapsedInheritedTypesName = protocolDeclaration.inheritedTypes
|
||||
if collapsedInheritedTypesName.contains(where: { $0 == "NSObjectProtocol" }) {
|
||||
return true
|
||||
} else {
|
||||
return protocolDeclaration.inheritedTypes.contains(where: { inheritanceType in
|
||||
containsRecursively(name: inheritanceType.name)
|
||||
})
|
||||
return protocolDeclaration.inheritedTypes.contains { inheritanceType in
|
||||
containsRecursively(name: inheritanceType)
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
let protocolDeclarationDictionary: [String: ProtocolDeclaration] = Dictionary(
|
||||
uniqueKeysWithValues: filesRepresentation.flatMap { file in
|
||||
file.declarations.compactMap { token -> (name: String, protocolDeclaration: ProtocolDeclaration)? in
|
||||
file.tokens.compactMap { token -> (name: String, protocolDeclaration: ProtocolDeclaration)? in
|
||||
guard let protocolDeclaration = token as? ProtocolDeclaration else { return nil }
|
||||
return (name: protocolDeclaration.name, protocolDeclaration: protocolDeclaration)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
let nsObjectProtocols: [ProtocolDeclaration] = protocolDeclarationDictionary.values.reduce(into: []) { accumulator, protocolDeclaration in
|
||||
let nsObjectProtocols: [ProtocolDeclaration] = protocolDeclarationDictionary.values.reduce(into: []) { protocols, protocolDeclaration in
|
||||
guard containsRecursively(name: protocolDeclaration.name) else { return }
|
||||
accumulator.append(protocolDeclaration)
|
||||
protocols.append(protocolDeclaration)
|
||||
}
|
||||
|
||||
return filesRepresentation.map { $0.inheritNSObject(subjects: nsObjectProtocols) }
|
||||
return filesRepresentation.map { $0.inheritNSObject(protocols: nsObjectProtocols) }
|
||||
}
|
||||
|
||||
private func removeTypes(from files: [FileRepresentation], using filters: [(Token) -> Bool]) -> [FileRepresentation] {
|
||||
private func removeTypes(from files: [FileRepresentation], using filters: [TokenFilter]) -> [FileRepresentation] {
|
||||
// Only keep those that pass all filters
|
||||
let filter: (Token) -> Bool = { token in
|
||||
!filters.contains { !$0(token) }
|
||||
let filter: TokenFilter = { token in
|
||||
guard token.isClass || token.isProtocol else { return true }
|
||||
return !filters.contains { !$0(token) }
|
||||
}
|
||||
|
||||
return files.compactMap { file in
|
||||
let filteredDeclarations = file.declarations.filter(filter)
|
||||
guard !filteredDeclarations.isEmpty else { return nil }
|
||||
return FileRepresentation(sourceFile: file.sourceFile, declarations: filteredDeclarations)
|
||||
let filteredTokens = file.tokens.filter(filter)
|
||||
guard !filteredTokens.isEmpty else { return nil }
|
||||
return file.replacing(tokens: filteredTokens)
|
||||
}
|
||||
}
|
||||
|
||||
// filter that keeps the protocols while removing all classes
|
||||
private func ignoreClasses(token: Token) -> Bool {
|
||||
return !(token is ClassDeclaration)
|
||||
!token.isClass
|
||||
}
|
||||
|
||||
// filter that keeps the classes/protocols that match the passed regular expression
|
||||
private func keepMatching(pattern: String) -> (Token) -> Bool {
|
||||
private func keepMatching(pattern: String) -> TokenFilter {
|
||||
do {
|
||||
let regex = try NSRegularExpression(pattern: pattern, options: [])
|
||||
|
||||
return { token in
|
||||
guard let containerToken = token as? ContainerToken else { return true }
|
||||
return regex.firstMatch(in: containerToken.name, options: [], range: NSMakeRange(0, containerToken.name.count)) != nil
|
||||
guard let namedToken = token as? HasName else { return true }
|
||||
return regex.firstMatch(in: namedToken.name, options: [], range: NSMakeRange(0, namedToken.name.count)) != nil
|
||||
}
|
||||
} catch {
|
||||
fatalError("Invalid regular expression: " + (error as NSError).description)
|
||||
|
@ -147,16 +148,16 @@ public struct GenerateMocksCommand: CommandProtocol {
|
|||
}
|
||||
|
||||
// filter that keeps only the classes/protocols that are not supposed to be excluded
|
||||
private func ignoreIfExists(in excluded: [String]) -> (Token) -> Bool {
|
||||
private func ignoreExcluded(in excluded: [String]) -> TokenFilter {
|
||||
let excludedSet = Set(excluded)
|
||||
return { token in
|
||||
guard let containerToken = token as? ContainerToken else { return true }
|
||||
guard let containerToken = token as? HasName else { return true }
|
||||
return !excludedSet.contains(containerToken.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public struct Options: OptionsProtocol {
|
||||
struct Options: OptionsProtocol {
|
||||
let files: [String]
|
||||
let output: String
|
||||
let noHeader: Bool
|
||||
|
@ -166,11 +167,11 @@ public struct GenerateMocksCommand: CommandProtocol {
|
|||
let exclude: [String]
|
||||
let filePrefix: String
|
||||
let noClassMocking: Bool
|
||||
let debugMode: Bool
|
||||
let globEnabled: Bool
|
||||
let isDebug: Bool
|
||||
let isGlobEnabled: Bool
|
||||
let regex: String
|
||||
|
||||
public init(
|
||||
init(
|
||||
output: String,
|
||||
testableFrameworks: String,
|
||||
exclude: String,
|
||||
|
@ -179,8 +180,8 @@ public struct GenerateMocksCommand: CommandProtocol {
|
|||
noInheritance: Bool,
|
||||
filePrefix: String,
|
||||
noClassMocking: Bool,
|
||||
debugMode: Bool,
|
||||
globEnabled: Bool,
|
||||
isDebug: Bool,
|
||||
isGlobEnabled: Bool,
|
||||
regex: String,
|
||||
files: [String]
|
||||
) {
|
||||
|
@ -192,14 +193,14 @@ public struct GenerateMocksCommand: CommandProtocol {
|
|||
self.noInheritance = noInheritance
|
||||
self.filePrefix = filePrefix
|
||||
self.noClassMocking = noClassMocking
|
||||
self.debugMode = debugMode
|
||||
self.globEnabled = globEnabled
|
||||
self.isDebug = isDebug
|
||||
self.isGlobEnabled = isGlobEnabled
|
||||
self.regex = regex
|
||||
self.files = files
|
||||
}
|
||||
|
||||
// all options are declared here and then parsed by Commandant
|
||||
public static func evaluate(_ m: CommandMode) -> Result<Options, CommandantError<CuckooGeneratorError>> {
|
||||
static func evaluate(_ m: CommandMode) -> Result<Options, CommandantError<CuckooGeneratorError>> {
|
||||
let output: Result<String, CommandantError<ClientError>> = m <| Option(key: "output", defaultValue: "GeneratedMocks.swift", usage: "Where to put the generated mocks.\nIf a path to a directory is supplied, each input file will have a respective output file with mocks.\nIf a path to a Swift file is supplied, all mocks will be in a single file.\nDefault value is `GeneratedMocks.swift`.")
|
||||
|
||||
let testable: Result<String, CommandantError<ClientError>> = m <| Option(key: "testable", defaultValue: "", usage: "A comma separated list of frameworks that should be imported as @testable in the mock files.")
|
||||
|
@ -216,14 +217,16 @@ public struct GenerateMocksCommand: CommandProtocol {
|
|||
|
||||
let noClassMocking: Result<Bool, CommandantError<ClientError>> = m <| Option(key: "no-class-mocking", defaultValue: false, usage: "Do not generate mocks for classes.")
|
||||
|
||||
let debugMode: Result<Bool, CommandantError<ClientError>> = m <| Switch(flag: "d", key: "debug", usage: "Run generator in debug mode.")
|
||||
let isDebug: Result<Bool, CommandantError<ClientError>> = m <| Switch(flag: "d", key: "debug", usage: "Run generator in debug mode.")
|
||||
|
||||
let globEnabled: Result<Bool, CommandantError<ClientError>> = m <| Switch(flag: "g", key: "glob", usage: "Use glob for specifying input paths.")
|
||||
let isGlobEnabled: Result<Bool, CommandantError<ClientError>> = m <| Switch(flag: "g", key: "glob", usage: "Use glob for specifying input paths.")
|
||||
|
||||
let regex: Result<String, CommandantError<ClientError>> = m <| Option(key: "regex", defaultValue: "", usage: "A regular expression pattern that is used to match Classes and Protocols.\nAll that do not match are excluded.\nCan be used alongside `--exclude`.")
|
||||
|
||||
let input: Result<[String], CommandantError<ClientError>> = m <| Argument(usage: "Files to parse and generate mocks for.")
|
||||
|
||||
// If you want to add an option, make sure to extend the `curry` function below.
|
||||
|
||||
return curry(Options.init)
|
||||
<*> output
|
||||
<*> testable
|
||||
|
@ -233,10 +236,19 @@ public struct GenerateMocksCommand: CommandProtocol {
|
|||
<*> noInheritance
|
||||
<*> filePrefix
|
||||
<*> noClassMocking
|
||||
<*> debugMode
|
||||
<*> globEnabled
|
||||
<*> isDebug
|
||||
<*> isGlobEnabled
|
||||
<*> regex
|
||||
<*> input
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unfortunately, Swift doesn't support variadic generic parameters as of now, so this monstrosity is necessary.
|
||||
private func curry<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, R>
|
||||
(_ f: @escaping (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R)
|
||||
->(P1)->(P2)->(P3)->(P4)->(P5)->(P6)->(P7)->(P8)->(P9)->(P10)->(P11)->(P12) -> R {
|
||||
return { p1 in { p2 in { p3 in { p4 in { p5 in { p6 in { p7 in { p8 in { p9 in { p10 in { p11 in { p12 in
|
||||
f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)
|
||||
} } } } } } } } } } } }
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import Foundation
|
||||
import Commandant
|
||||
import Result
|
||||
|
||||
struct VersionCommand: CommandProtocol {
|
||||
|
||||
static let appVersion = Bundle.allFrameworks.filter {
|
||||
$0.bundleIdentifier == "org.brightify.CuckooGeneratorFramework"
|
||||
}.first?.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? ""
|
||||
|
||||
let verb = "version"
|
||||
let function = "Prints the version of this generator."
|
||||
|
||||
func run(_ options: Options) -> Result<Void, CuckooGeneratorError> {
|
||||
print(VersionCommand.appVersion)
|
||||
return .success(())
|
||||
}
|
||||
|
||||
struct Options: OptionsProtocol {
|
||||
static func evaluate(_ m: CommandMode) -> Result<Options, CommandantError<CuckooGeneratorError>> {
|
||||
return .success(Options())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,458 @@
|
|||
import Foundation
|
||||
import SwiftSyntax
|
||||
import SwiftSyntaxParser
|
||||
|
||||
final class Crawler: SyntaxVisitor {
|
||||
static func crawl(url: URL) throws -> Crawler {
|
||||
let syntaxTree = try SyntaxParser.parse(url)
|
||||
#if DEBUG
|
||||
// Comment out the line above and uncomment the one below to test specific strings.
|
||||
// The `testString` is at the bottom of this file.
|
||||
// let syntaxTree = try SyntaxParser.parse(source: testString)
|
||||
#endif
|
||||
let crawler = Self(container: nil)
|
||||
crawler.walk(syntaxTree)
|
||||
return crawler
|
||||
}
|
||||
|
||||
var imports: [Import] = []
|
||||
var tokens: [Token] = []
|
||||
|
||||
private var container: Reference<Token>?
|
||||
|
||||
private init(container: Reference<Token>?) {
|
||||
self.container = container
|
||||
}
|
||||
|
||||
override func visit(_ node: ImportDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
let path = node.path.description
|
||||
if let importKind = node.importKind?.withoutTrivia().description {
|
||||
// Component import.
|
||||
imports.append(.component(kind: importKind, name: path))
|
||||
} else {
|
||||
// Target import.
|
||||
imports.append(.library(name: path))
|
||||
}
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
log(node)
|
||||
|
||||
// Skip `final` classes.
|
||||
guard !node.modifiers.isFinal else { return .skipChildren }
|
||||
|
||||
var token = ClassDeclaration(
|
||||
parent: container,
|
||||
attributes: attributes(from: node.attributes),
|
||||
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
|
||||
name: node.identifier.withoutTrivia().description,
|
||||
genericParameters: genericParameters(from: node.genericParameterClause?.genericParameterList),
|
||||
genericRequirements: genericRequirements(from: node.genericWhereClause?.requirementList),
|
||||
inheritedTypes: inheritedTypes(from: node.inheritanceClause?.inheritedTypeCollection),
|
||||
members: []
|
||||
)
|
||||
|
||||
// Early return for private namespace.
|
||||
guard token.accessibility.isAccessible else { return .skipChildren }
|
||||
|
||||
let crawler = Crawler(container: Reference(token))
|
||||
crawler.walk(members: node.members)
|
||||
token.members = crawler.tokens
|
||||
tokens.append(token)
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
log(node)
|
||||
let inheritedTypes = inheritedTypes(from: node.inheritanceClause?.inheritedTypeCollection)
|
||||
var token = ProtocolDeclaration(
|
||||
parent: container,
|
||||
attributes: attributes(from: node.attributes),
|
||||
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
|
||||
name: node.identifier.withoutTrivia().description,
|
||||
genericParameters: genericParameters(from: node.primaryAssociatedTypeClause?.primaryAssociatedTypeList) + associatedTypes(from: node.members.members),
|
||||
genericRequirements: genericRequirements(from: node.genericWhereClause?.requirementList),
|
||||
inheritedTypes: inheritedTypes,
|
||||
members: []
|
||||
)
|
||||
|
||||
// Early return for private namespace.
|
||||
guard token.accessibility.isAccessible else { return .skipChildren }
|
||||
|
||||
let crawler = Crawler(container: Reference(token))
|
||||
crawler.walk(members: node.members)
|
||||
token.members = crawler.tokens
|
||||
tokens.append(token)
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
// Enum mocking is not supported, this is used to parse nested classes.
|
||||
override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
log(node)
|
||||
var token = NamespaceDeclaration(
|
||||
parent: container,
|
||||
attributes: attributes(from: node.attributes),
|
||||
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
|
||||
name: node.identifier.withoutTrivia().description,
|
||||
members: []
|
||||
)
|
||||
|
||||
// Early return for private namespace.
|
||||
guard token.accessibility.isAccessible else { return .skipChildren }
|
||||
|
||||
let crawler = Crawler(container: Reference(token))
|
||||
crawler.walk(members: node.members)
|
||||
token.members = crawler.tokens
|
||||
tokens.append(token)
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
// Extension mocking is not supported, this is used to parse nested classes.
|
||||
override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
log(node)
|
||||
var token = NamespaceDeclaration(
|
||||
parent: container,
|
||||
attributes: attributes(from: node.attributes),
|
||||
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
|
||||
name: node.extendedType.withoutTrivia().description,
|
||||
members: []
|
||||
)
|
||||
|
||||
// Early return for private namespace.
|
||||
guard token.accessibility.isAccessible else { return .skipChildren }
|
||||
|
||||
let crawler = Crawler(container: Reference(token))
|
||||
crawler.walk(members: node.members)
|
||||
token.members = crawler.tokens
|
||||
tokens.append(token)
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
// Struct mocking is not supported, this is used to parse nested classes.
|
||||
override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
log(node)
|
||||
var token = NamespaceDeclaration(
|
||||
parent: container,
|
||||
attributes: attributes(from: node.attributes),
|
||||
accessibility: accessibility(from: node.modifiers) ?? (container as? HasAccessibility)?.accessibility ?? .internal,
|
||||
name: node.identifier.withoutTrivia().description,
|
||||
members: []
|
||||
)
|
||||
|
||||
// Early return for private namespace.
|
||||
guard token.accessibility.isAccessible else { return .skipChildren }
|
||||
|
||||
let crawler = Crawler(container: Reference(token))
|
||||
crawler.walk(members: node.members)
|
||||
token.members = crawler.tokens
|
||||
tokens.append(token)
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
tokens.append(contentsOf: parse(node.withoutTrivia()))
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
// TODO: Print the error.
|
||||
if let initializer = try! parse(node.withoutTrivia()) {
|
||||
tokens.append(initializer)
|
||||
}
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
// TODO: Print the error.
|
||||
if let method = try! parse(node.withoutTrivia()) {
|
||||
tokens.append(method)
|
||||
}
|
||||
return .skipChildren
|
||||
}
|
||||
|
||||
private func walk(members: MemberDeclBlockSyntax) {
|
||||
for member in members.members {
|
||||
walk(member.withoutTrivia())
|
||||
}
|
||||
}
|
||||
|
||||
private func log(_ node: DeclSyntaxProtocol, additionalInfo: String? = nil) {
|
||||
#if !DEBUG
|
||||
return
|
||||
#endif
|
||||
|
||||
let description: String
|
||||
switch node {
|
||||
case let node as ClassDeclSyntax:
|
||||
description = "class \(node.identifier.withoutTrivia().description)"
|
||||
case let node as ProtocolDeclSyntax:
|
||||
description = "protocol \(node.identifier.withoutTrivia().description)"
|
||||
case let node as StructDeclSyntax:
|
||||
description = "struct \(node.identifier.withoutTrivia().description)"
|
||||
case let node as ExtensionDeclSyntax:
|
||||
description = "extension \(node.extendedType.withoutTrivia().description)"
|
||||
default:
|
||||
description = "Unknown declaration \(node.withoutTrivia().description)"
|
||||
}
|
||||
|
||||
print([description, additionalInfo].compactMap { $0 }.joined(separator: " "))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Variable crawling.
|
||||
extension Crawler {
|
||||
private func parse(_ variableGroup: VariableDeclSyntax) -> [Variable] {
|
||||
let isConstant = variableGroup.letOrVarKeyword.tokenKind == .letKeyword
|
||||
|
||||
guard !isConstant && !variableGroup.modifiers.isStatic && !variableGroup.modifiers.isFinal else { return [] }
|
||||
|
||||
let attributes = attributes(from: variableGroup.attributes)
|
||||
|
||||
var accessibility = Accessibility.internal
|
||||
var setterAccessibility: Accessibility?
|
||||
if let modifiers = variableGroup.modifiers {
|
||||
for modifier in modifiers {
|
||||
let tokenKind = modifier.name.tokenKind
|
||||
|
||||
guard let parsedAccessibility = Accessibility(tokenKind: tokenKind) else {
|
||||
continue
|
||||
}
|
||||
|
||||
if case .identifier(let detail) = modifier.detail?.tokenKind, detail == "set" {
|
||||
setterAccessibility = parsedAccessibility
|
||||
} else {
|
||||
accessibility = parsedAccessibility
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unnecessary now, but might come in handy later.
|
||||
// let isOverriding = variableGroup.modifiers?.contains { $0.name.tokenKind == .identifier("override") } ?? false
|
||||
|
||||
return variableGroup.bindings
|
||||
.compactMap(variable(from:))
|
||||
.map {
|
||||
Variable(
|
||||
parent: container,
|
||||
attributes: attributes,
|
||||
accessibility: accessibility,
|
||||
setterAccessibility: $0.isReadOnly ? nil : setterAccessibility ?? (container as? HasAccessibility)?.accessibility ?? .internal,
|
||||
name: $0.identifier,
|
||||
type: $0.type,
|
||||
isOverriding: container?.isClass ?? false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func variable(from binding: PatternBindingSyntax) -> VariablePart? {
|
||||
guard case .identifier(let identifier) = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.tokenKind else { return nil }
|
||||
|
||||
let type: String
|
||||
if let explicitType = binding.typeAnnotation?.type.withoutTrivia().description {
|
||||
type = explicitType
|
||||
} else if let initializer = binding.initializer?.value.withoutTrivia().description {
|
||||
type = TypeGuesser.guessType(from: initializer)!
|
||||
} else {
|
||||
fatalError("TODO: Can't infer type.")
|
||||
}
|
||||
|
||||
let isReadOnly: Bool
|
||||
if let accessor = binding.accessor {
|
||||
let accessorsContainSet = accessor.as(AccessorBlockSyntax.self)?.accessors
|
||||
.contains { $0.accessorKind.tokenKind == .contextualKeyword("set") } ?? false
|
||||
isReadOnly = !accessorsContainSet
|
||||
} else {
|
||||
isReadOnly = false
|
||||
}
|
||||
|
||||
return VariablePart(
|
||||
identifier: identifier,
|
||||
type: WrappableType(parsing: type),
|
||||
isReadOnly: isReadOnly
|
||||
)
|
||||
}
|
||||
|
||||
private struct VariablePart {
|
||||
var identifier: String
|
||||
var type: WrappableType
|
||||
var isReadOnly: Bool
|
||||
}
|
||||
}
|
||||
|
||||
extension Crawler {
|
||||
private func parse(_ initializer: InitializerDeclSyntax) throws -> Initializer? {
|
||||
Initializer(
|
||||
parent: container,
|
||||
attributes: attributes(from: initializer.attributes),
|
||||
accessibility: initializer.modifiers?.lazy.compactMap { Accessibility(tokenKind: $0.name.tokenKind) }.first ?? (container as? HasAccessibility)?.accessibility ?? .internal,
|
||||
signature: Method.Signature(
|
||||
genericParameters: genericParameters(from: initializer.genericParameterClause?.genericParameterList),
|
||||
parameters: try parameters(from: initializer.parameters.parameterList),
|
||||
asyncType: nil,
|
||||
throwType: initializer.throwsOrRethrowsKeyword.flatMap { ThrowType(rawValue: $0.withoutTrivia().description) },
|
||||
returnType: nil,
|
||||
whereConstraints: genericRequirements(from: initializer.genericWhereClause?.requirementList)
|
||||
),
|
||||
isRequired: initializer.modifiers?.contains { $0.name.tokenKind == .identifier("required") } ?? false,
|
||||
isOptional: initializer.optionalMark?.isPresent == true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Method crawling.
|
||||
extension Crawler {
|
||||
private func parse(_ method: FunctionDeclSyntax) throws -> Method? {
|
||||
// Can't mock static and final members.
|
||||
guard !method.modifiers.isStatic && !method.modifiers.isFinal else { return nil }
|
||||
|
||||
guard case .identifier(let identifier) = method.identifier.tokenKind else { return nil }
|
||||
|
||||
return Method(
|
||||
parent: container,
|
||||
attributes: attributes(from: method.attributes),
|
||||
accessibility: method.modifiers?.lazy.compactMap { Accessibility(tokenKind: $0.name.tokenKind) }.first ?? (container as? HasAccessibility)?.accessibility ?? .internal,
|
||||
name: identifier,
|
||||
signature: Method.Signature(
|
||||
genericParameters: genericParameters(from: method.genericParameterClause?.genericParameterList),
|
||||
parameters: try parameters(from: method.signature.input.parameterList),
|
||||
asyncType: method.signature.asyncOrReasyncKeyword.flatMap { AsyncType(rawValue: $0.withoutTrivia().description) },
|
||||
throwType: method.signature.throwsOrRethrowsKeyword.flatMap { ThrowType(rawValue: $0.withoutTrivia().description) },
|
||||
returnType: method.signature.output.map { WrappableType(parsing: $0.returnType.withoutTrivia().description) } ?? WrappableType.type("Void"),
|
||||
whereConstraints: genericRequirements(from: method.genericWhereClause?.requirementList)
|
||||
),
|
||||
isOptional: method.modifiers?.contains { $0.name.tokenKind == .identifier("optional") } ?? false,
|
||||
isOverriding: container?.isClass ?? false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension Crawler {
|
||||
private func parameters(from parameterList: FunctionParameterListSyntax) throws -> [MethodParameter] {
|
||||
try parameterList.map { parameter in
|
||||
guard let name = parameter.firstName?.withoutTrivia().description else { throw CrawlError.parameterNameMissing }
|
||||
guard let type = parameter.type else { throw CrawlError.parameterTypeMissing }
|
||||
|
||||
let bareType: String
|
||||
let isInout: Bool
|
||||
if let attributedType = type.as(AttributedTypeSyntax.self) {
|
||||
isInout = attributedType.specifier?.tokenKind == .inoutKeyword
|
||||
bareType = attributedType.withSpecifier(nil).description
|
||||
} else {
|
||||
isInout = false
|
||||
bareType = type.description
|
||||
}
|
||||
|
||||
let fullType = "\(bareType)\((parameter.ellipsis?.isPresent ?? false) ? "..." : "")"
|
||||
|
||||
return MethodParameter(
|
||||
name: name,
|
||||
innerName: nil,
|
||||
type: WrappableType(parsing: fullType),
|
||||
isInout: isInout
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func attributes(from attributeList: AttributeListSyntax?) -> [Attribute] {
|
||||
attributeList?.children.compactMap { attribute in
|
||||
guard let attribute = attribute.as(AttributeSyntax.self) else { return nil }
|
||||
switch attribute.attributeName.tokenKind {
|
||||
case .identifier("available"):
|
||||
return .available(
|
||||
arguments: attribute.argument?.description
|
||||
.split(separator: ",")
|
||||
.map { String($0).trimmed } ?? []
|
||||
)
|
||||
default:
|
||||
print("Unsupported attribute '\(attribute.attributeName.text)'")
|
||||
return nil
|
||||
}
|
||||
} ?? []
|
||||
}
|
||||
|
||||
private func accessibility(from modifierList: ModifierListSyntax?) -> Accessibility? {
|
||||
modifierList?.lazy.compactMap { Accessibility(tokenKind: $0.name.tokenKind) }.first
|
||||
}
|
||||
|
||||
private func genericParameters(from genericParameterList: GenericParameterListSyntax?) -> [GenericParameter] {
|
||||
genericParameterList?.map { genericParameter in
|
||||
GenericParameter(
|
||||
name: genericParameter.name.description,
|
||||
inheritedTypes: genericParameter.inheritedType.map(inheritedTypes(from:)) ?? []
|
||||
)
|
||||
} ?? []
|
||||
}
|
||||
|
||||
private func genericParameters(from primaryAssociatedTypeList: PrimaryAssociatedTypeListSyntax?) -> [GenericParameter] {
|
||||
primaryAssociatedTypeList?.compactMap { associatedType in
|
||||
guard case .identifier(let identifier) = associatedType.name.tokenKind else { return nil }
|
||||
return GenericParameter(
|
||||
name: identifier,
|
||||
inheritedTypes: associatedType.inheritedType.map(inheritedTypes(from:)) ?? []
|
||||
)
|
||||
} ?? []
|
||||
}
|
||||
|
||||
private func associatedTypes(from memberList: MemberDeclListSyntax) -> [GenericParameter] {
|
||||
memberList
|
||||
.compactMap { member in
|
||||
guard let associatedType = member.decl.as(AssociatedtypeDeclSyntax.self),
|
||||
case .identifier(let identifier) = associatedType.identifier.tokenKind else { return nil }
|
||||
|
||||
return GenericParameter(
|
||||
name: identifier,
|
||||
inheritedTypes: inheritedTypes(from: associatedType.inheritanceClause?.inheritedTypeCollection)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func genericRequirements(from genericRequirementList: GenericRequirementListSyntax?) -> [String] {
|
||||
genericRequirementList?.map { $0.body.withoutTrivia().description } ?? []
|
||||
}
|
||||
|
||||
private func inheritedTypes(from inheritedTypesList: InheritedTypeListSyntax?) -> [String] {
|
||||
inheritedTypesList?.flatMap { inheritedType -> [String] in
|
||||
inheritedTypes(from: inheritedType.typeName)
|
||||
} ?? []
|
||||
}
|
||||
|
||||
private func inheritedTypes(from inheritedType: TypeSyntax) -> [String] {
|
||||
if let simpleType = inheritedType.as(SimpleTypeIdentifierSyntax.self) {
|
||||
return [simpleType.withoutTrivia().description]
|
||||
} else if let compositeType = inheritedType.as(CompositionTypeSyntax.self) {
|
||||
return compositeType.elements.compactMap { element in
|
||||
guard let simpleType = element.type
|
||||
.as(SimpleTypeIdentifierSyntax.self) else {
|
||||
return nil
|
||||
}
|
||||
return simpleType.withoutTrivia().description
|
||||
}
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Crawler {
|
||||
enum CrawlError: Error {
|
||||
case parameterNameMissing
|
||||
case parameterTypeMissing
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
extension Crawler {
|
||||
private static let testString =
|
||||
"""
|
||||
class Multi {
|
||||
@available(iOS 42.0, *)
|
||||
var gg: Bool = false
|
||||
}
|
||||
|
||||
protocol Brek {
|
||||
func drak()
|
||||
}
|
||||
"""
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
import SwiftSyntax
|
||||
|
||||
extension Optional where Wrapped == ModifierListSyntax {
|
||||
var isFinal: Bool {
|
||||
self?.isFinal ?? false
|
||||
}
|
||||
|
||||
var isStatic: Bool {
|
||||
self?.isStatic ?? false
|
||||
}
|
||||
}
|
||||
|
||||
extension ModifierListSyntax {
|
||||
var isFinal: Bool {
|
||||
contains { $0.name.tokenKind == .identifier("final") }
|
||||
}
|
||||
|
||||
var isStatic: Bool {
|
||||
contains { $0.name.tokenKind == .staticKeyword }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
import Foundation
|
||||
import FileKit
|
||||
|
||||
struct FileHeaderHandler {
|
||||
|
||||
static func header(for file: FileRepresentation, timestamp: String?) -> String {
|
||||
let path = getRelativePath(to: file)
|
||||
return [
|
||||
"// MARK: - Mocks generated from file: '\(path)'",
|
||||
timestamp.map { "at \($0)" },
|
||||
]
|
||||
.compactMap { $0 }
|
||||
.joined(separator: " ")
|
||||
}
|
||||
|
||||
static func imports(for file: FileRepresentation, testableFrameworks: [String]) -> String {
|
||||
let testableImports = testableFrameworks
|
||||
.map { frameworkName in
|
||||
String(frameworkName.map { $0.isLetter || $0.isWholeNumber ? $0 : "_" })
|
||||
}
|
||||
.map { "@testable import \($0)" }
|
||||
return [
|
||||
["import Cuckoo"],
|
||||
OrderedSet(file.imports).values.map { "import \($0)" },
|
||||
testableImports,
|
||||
]
|
||||
.flatMap { $0 }
|
||||
.joined(separator: "\n")
|
||||
}
|
||||
|
||||
private static func getRelativePath(to file: FileRepresentation) -> String {
|
||||
let path = file.file.path.absolute
|
||||
let base = path.commonAncestor(Path.current)
|
||||
let components = path.components.suffix(from: base.components.endIndex)
|
||||
let result = components.map { $0.rawValue }.joined(separator: Path.separator)
|
||||
let difference = Path.current.components.endIndex - base.components.endIndex
|
||||
return (0..<difference).reduce(result) { acc, _ in ".." + Path.separator + acc }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
import Foundation
|
||||
import Stencil
|
||||
|
||||
struct Generator {
|
||||
|
||||
private static let reservedKeywordsNotAllowedAsMethodName: Set = [
|
||||
// Keywords used in declarations:
|
||||
"associatedtype", "class", "deinit", "enum", "extension", "fileprivate", "func", "import", "init", "inout", "internal", "let", "operator", "private", "precedencegroup", "protocol", "public", "rethrows", "static", "struct", "subscript", "typealias", "var",
|
||||
// Keywords used in statements:
|
||||
"break", "case", "catch", "continue", "default", "defer", "do", "else", "fallthrough", "for", "guard", "if", "in", "repeat", "return", "throw", "switch", "where", "while",
|
||||
// Keywords used in expressions and types:
|
||||
"Any", "as", "catch", "false", "is", "nil", "rethrows", "self", "super", "throw", "throws", "true", "try",
|
||||
// Keywords used in patterns:
|
||||
"_",
|
||||
]
|
||||
|
||||
private static let extensions = createExtensions()
|
||||
|
||||
static func generate(tokens: [Token], debug: Bool = false) throws -> String {
|
||||
let containers = tokens.map { $0.serialize() }
|
||||
|
||||
let environment = Environment(
|
||||
extensions: extensions,
|
||||
trimBehaviour: .smart
|
||||
)
|
||||
return try environment.renderTemplate(string: Templates.mock, context: ["containers": containers, "debug": debug])
|
||||
}
|
||||
|
||||
private static func matchableGenericTypes(from method: Method) -> String {
|
||||
guard !method.signature.parameters.isEmpty || !method.signature.genericParameters.isEmpty else { return "" }
|
||||
|
||||
let matchableGenericParameters = method.signature.parameters.enumerated().map { index, parameter -> String in
|
||||
let type = parameter.isOptional ? "OptionalMatchable" : "Matchable"
|
||||
return "M\(index + 1): Cuckoo.\(type)"
|
||||
}
|
||||
let methodGenericParameters = method.signature.genericParameters.map { $0.description }
|
||||
return "<\((matchableGenericParameters + methodGenericParameters).joined(separator: ", "))>"
|
||||
}
|
||||
|
||||
private static func matchableGenericsWhereClause(from method: Method) -> String {
|
||||
guard method.signature.parameters.isEmpty == false else { return "" }
|
||||
|
||||
let matchableWhereConstraints = method.signature.parameters.enumerated().map { index, parameter -> String in
|
||||
let type = parameter.isOptional ? "OptionalMatchedType" : "MatchedType"
|
||||
return "M\(index + 1).\(type) == \(genericSafeType(from: parameter.type.withoutAttributes.unoptionaled.sugarized))"
|
||||
}
|
||||
let methodWhereConstraints = method.signature.whereConstraints
|
||||
return " where \((matchableWhereConstraints + methodWhereConstraints).joined(separator: ", "))"
|
||||
}
|
||||
|
||||
private static func matchableParameterSignature(with parameters: [MethodParameter]) -> String {
|
||||
guard !parameters.isEmpty else { return "" }
|
||||
|
||||
return parameters.enumerated()
|
||||
.map { "\($1.nameAndInnerName): M\($0 + 1)" }
|
||||
.joined(separator: ", ")
|
||||
}
|
||||
|
||||
private static func parameterMatchers(for parameters: [MethodParameter]) -> String {
|
||||
guard parameters.isEmpty == false else { return "let matchers: [Cuckoo.ParameterMatcher<Void>] = []" }
|
||||
|
||||
let tupleType = parameters.map { $0.typeWithoutAttributes }.joined(separator: ", ")
|
||||
let matchers = parameters
|
||||
.compactMap { parameter -> MethodParameter? in
|
||||
if parameter.usableName == nil {
|
||||
return nil
|
||||
} else {
|
||||
return parameter
|
||||
}
|
||||
}
|
||||
// Enumeration is done after filtering out parameters without usable names.
|
||||
.enumerated()
|
||||
.compactMap { index, parameter in
|
||||
"wrap(matchable: \(parameter.usableName)) { $0\(parameters.count > 1 ? ".\(index)" : "") }"
|
||||
}
|
||||
.joined(separator: ", ")
|
||||
return "let matchers: [Cuckoo.ParameterMatcher<(\(genericSafeType(from: tupleType)))>] = [\(matchers)]"
|
||||
}
|
||||
|
||||
private static func genericSafeType(from type: String) -> String {
|
||||
return type.replacingOccurrences(of: "!", with: "?")
|
||||
}
|
||||
|
||||
private static func openNestedClosure(for method: Method) -> String {
|
||||
var fullString = ""
|
||||
for (index, parameter) in method.signature.parameters.enumerated() {
|
||||
if parameter.isClosure && !parameter.isEscaping {
|
||||
let indents = String(repeating: "\t", count: index)
|
||||
let tries = method.isThrowing ? "try " : ""
|
||||
let awaits = method.isAsync ? "await " : ""
|
||||
|
||||
let sugarizedReturnType = method.returnType?.sugarized
|
||||
let returnSignature: String
|
||||
if let sugarizedReturnType {
|
||||
if sugarizedReturnType.isEmpty {
|
||||
returnSignature = sugarizedReturnType
|
||||
} else {
|
||||
returnSignature = " -> \(sugarizedReturnType)"
|
||||
}
|
||||
} else {
|
||||
returnSignature = ""
|
||||
}
|
||||
|
||||
fullString += "\(indents)return \(tries)\(awaits)withoutActuallyEscaping(\(parameter.usableName), do: { (\(parameter.usableName): @escaping \(parameter.type))\(returnSignature) in\n"
|
||||
}
|
||||
}
|
||||
|
||||
return fullString
|
||||
}
|
||||
|
||||
private static func closeNestedClosure(for parameters: [MethodParameter]) -> String {
|
||||
var fullString = ""
|
||||
for (index, parameter) in parameters.enumerated() {
|
||||
if parameter.isClosure && !parameter.isEscaping {
|
||||
let indents = String(repeating: "\t", count: index)
|
||||
fullString += "\(indents)})\n"
|
||||
}
|
||||
}
|
||||
return fullString
|
||||
}
|
||||
|
||||
private static func escapeReservedKeywords(for name: String) -> String {
|
||||
Self.reservedKeywordsNotAllowedAsMethodName.contains(name) ? "`\(name)`" : name
|
||||
}
|
||||
|
||||
private static func removeClosureArgumentNames(for type: String) -> String {
|
||||
type.replacingOccurrences(
|
||||
of: "_\\s+?[_a-zA-Z]\\w*?\\s*?:",
|
||||
with: "",
|
||||
options: .regularExpression
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension Generator {
|
||||
private static func createExtensions() -> [Extension] {
|
||||
let stencilExtension = Extension()
|
||||
|
||||
stencilExtension
|
||||
.registeringFilter("genericSafe") { (value: Any?) in
|
||||
guard let string = value as? String else { return value }
|
||||
return genericSafeType(from: string)
|
||||
}
|
||||
.registeringFilter("matchableGenericNames") { (value: Any?) in
|
||||
guard let method = value as? Method else { return value }
|
||||
return matchableGenericTypes(from: method)
|
||||
}
|
||||
.registeringFilter("matchableGenericWhereClause") { (value: Any?) in
|
||||
guard let method = value as? Method else { return value }
|
||||
return matchableGenericsWhereClause(from: method)
|
||||
}
|
||||
.registeringFilter("matchableParameterSignature") { (value: Any?) in
|
||||
guard let parameters = value as? [MethodParameter] else { return value }
|
||||
return matchableParameterSignature(with: parameters)
|
||||
}
|
||||
.registeringFilter("parameterMatchers") { (value: Any?) in
|
||||
guard let parameters = value as? [MethodParameter] else { return value }
|
||||
return parameterMatchers(for: parameters)
|
||||
}
|
||||
.registeringFilter("openNestedClosure") { (value: Any?) in
|
||||
guard let method = value as? Method else { return value }
|
||||
return openNestedClosure(for: method)
|
||||
}
|
||||
.registeringFilter("closeNestedClosure") { (value: Any?) in
|
||||
guard let parameters = value as? [MethodParameter] else { return value }
|
||||
return closeNestedClosure(for: parameters)
|
||||
}
|
||||
.registeringFilter("escapeReservedKeywords") { (value: Any?) in
|
||||
guard let name = value as? String else { return value }
|
||||
return escapeReservedKeywords(for: name)
|
||||
}
|
||||
.registeringFilter("removeClosureArgumentNames") { (value: Any?) in
|
||||
guard let type = value as? String else { return value }
|
||||
return removeClosureArgumentNames(for: type)
|
||||
}
|
||||
.registeringFilter("withSpace") { (value: Any?) in
|
||||
if let value = value as? String, !value.isEmpty {
|
||||
return "\(value) "
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
return [stencilExtension]
|
||||
}
|
||||
}
|
||||
|
||||
extension Extension {
|
||||
@discardableResult
|
||||
fileprivate func registeringFilter(_ name: String, filter: @escaping (Any?) throws -> Any?) -> Self {
|
||||
registerFilter(name, filter: filter)
|
||||
return self
|
||||
}
|
||||
|
||||
fileprivate func registeringFilter(_ name: String, filter: @escaping (Any?, [Any?]) throws -> Any?) -> Self {
|
||||
registerFilter(name, filter: filter)
|
||||
return self
|
||||
}
|
||||
|
||||
fileprivate func registeringFilter(_ name: String, filter: @escaping (Any?, [Any?], Context) throws -> Any?) -> Self {
|
||||
registerFilter(name, filter: filter)
|
||||
return self
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import Foundation
|
||||
|
||||
extension String {
|
||||
var nilIfEmpty: String? {
|
||||
isEmpty ? nil : self
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
subscript(range: NSRange) -> String {
|
||||
let fromIndex = self.index(self.startIndex, offsetBy: range.location)
|
||||
let toIndex = self.index(fromIndex, offsetBy: range.length)
|
||||
return String(self[fromIndex..<toIndex])
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
func stringMatch(from match: NSTextCheckingResult, at range: Int = 0) -> String {
|
||||
let matchRange = match.range(at: range)
|
||||
let fromIndex = index(startIndex, offsetBy: matchRange.location)
|
||||
let toIndex = index(fromIndex, offsetBy: matchRange.length)
|
||||
return String(self[fromIndex..<toIndex])
|
||||
}
|
||||
|
||||
func removing(match: NSTextCheckingResult, at range: Int = 0) -> String {
|
||||
let matchRange = match.range(at: range)
|
||||
let fromIndex = index(startIndex, offsetBy: matchRange.location)
|
||||
let toIndex = index(fromIndex, offsetBy: matchRange.length)
|
||||
|
||||
var mutableString = self
|
||||
mutableString.removeSubrange(fromIndex..<toIndex)
|
||||
return mutableString
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
import Foundation
|
||||
|
||||
struct OrderedSet<Element: Hashable>: ExpressibleByArrayLiteral {
|
||||
var values: [Element] {
|
||||
orderedSet.array as! [Element]
|
||||
}
|
||||
|
||||
private let orderedSet: NSMutableOrderedSet
|
||||
|
||||
init() {
|
||||
orderedSet = NSMutableOrderedSet()
|
||||
}
|
||||
|
||||
init(arrayLiteral elements: Element...) {
|
||||
self.init(elements)
|
||||
}
|
||||
|
||||
init(_ array: [Element]) {
|
||||
orderedSet = NSMutableOrderedSet(array: array)
|
||||
}
|
||||
|
||||
private init(orderedSet: NSMutableOrderedSet) {
|
||||
self.orderedSet = orderedSet
|
||||
}
|
||||
|
||||
func contains(_ member: Element) -> Bool {
|
||||
orderedSet.contains(member)
|
||||
}
|
||||
|
||||
mutating func insert(_ newMember: Element) {
|
||||
orderedSet.add(newMember)
|
||||
}
|
||||
|
||||
mutating func remove(_ member: Element) {
|
||||
orderedSet.remove(member)
|
||||
}
|
||||
|
||||
func union(_ other: OrderedSet<Element>) -> OrderedSet<Element> {
|
||||
withoutMutating { orderedSet in
|
||||
orderedSet.union(other.orderedSet)
|
||||
}
|
||||
}
|
||||
|
||||
func intersection(_ other: OrderedSet<Element>) -> OrderedSet<Element> {
|
||||
withoutMutating { orderedSet in
|
||||
orderedSet.intersect(other.orderedSet)
|
||||
}
|
||||
}
|
||||
|
||||
private func withoutMutating(work: (NSMutableOrderedSet) -> Void) -> OrderedSet<Element> {
|
||||
let orderedSetCopy = orderedSet.mutableCopy() as! NSMutableOrderedSet
|
||||
work(orderedSetCopy)
|
||||
return OrderedSet(orderedSet: orderedSetCopy)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import Foundation
|
||||
|
||||
@dynamicMemberLookup
|
||||
final class Reference<Value> {
|
||||
private(set) var value: Value
|
||||
|
||||
init(_ value: Value) {
|
||||
self.value = value
|
||||
}
|
||||
|
||||
subscript<T>(dynamicMember keyPath: KeyPath<Value, T>) -> T {
|
||||
value[keyPath: keyPath]
|
||||
}
|
||||
|
||||
subscript<T>(dynamicMember keyPath: WritableKeyPath<Value, T>) -> T {
|
||||
get { value[keyPath: keyPath] }
|
||||
set { value[keyPath: keyPath] = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
extension Reference: Equatable where Value: Equatable {
|
||||
static func == (lhs: Reference<Value>, rhs: Reference<Value>) -> Bool {
|
||||
lhs.value == rhs.value
|
||||
}
|
||||
}
|
|
@ -1,19 +1,20 @@
|
|||
#if NO_COMPILE
|
||||
import Foundation
|
||||
import SourceKittenFramework
|
||||
|
||||
public struct Tokenizer {
|
||||
struct SourceKittenTokenizer {
|
||||
private let file: File
|
||||
private let source: String
|
||||
private let debugMode: Bool
|
||||
|
||||
public init(sourceFile: File, debugMode: Bool) {
|
||||
init(sourceFile: File, debugMode: Bool) {
|
||||
self.file = sourceFile
|
||||
self.debugMode = debugMode
|
||||
|
||||
source = sourceFile.contents
|
||||
}
|
||||
|
||||
public func tokenize() -> FileRepresentation {
|
||||
func tokenize() -> FileRepresentation {
|
||||
do {
|
||||
let structure = try Structure(file: file)
|
||||
|
||||
|
@ -43,8 +44,8 @@ public struct Tokenizer {
|
|||
guard let dictionary = representable as? [String: SourceKitRepresentable] else { return nil }
|
||||
|
||||
// Common fields
|
||||
let name = dictionary[Key.Name.rawValue] as? String ?? Tokenizer.nameNotSet
|
||||
let kind = dictionary[Key.Kind.rawValue] as? String ?? Tokenizer.unknownType
|
||||
let name = dictionary[Key.Name.rawValue] as? String ?? Self.nameNotSet
|
||||
let kind = dictionary[Key.Kind.rawValue] as? String ?? Self.unknownType
|
||||
|
||||
// Inheritance
|
||||
let inheritedTypes = dictionary[Key.InheritedTypes.rawValue] as? [SourceKitRepresentable] ?? []
|
||||
|
@ -52,7 +53,7 @@ public struct Tokenizer {
|
|||
guard let typeDict = type as? [String: SourceKitRepresentable] else {
|
||||
return InheritanceDeclaration.empty
|
||||
}
|
||||
let name = typeDict[Key.Name.rawValue] as? String ?? Tokenizer.nameNotSet
|
||||
let name = typeDict[Key.Name.rawValue] as? String ?? Self.nameNotSet
|
||||
return InheritanceDeclaration(name: name)
|
||||
}
|
||||
|
||||
|
@ -103,9 +104,9 @@ public struct Tokenizer {
|
|||
return ProtocolDeclaration(
|
||||
name: name,
|
||||
accessibility: accessibility,
|
||||
range: range!,
|
||||
nameRange: nameRange!,
|
||||
bodyRange: bodyRange!,
|
||||
// range: range!,
|
||||
// nameRange: nameRange!,
|
||||
// bodyRange: bodyRange!,
|
||||
initializers: initializers,
|
||||
children: children,
|
||||
inheritedTypes: tokenizedInheritedTypes,
|
||||
|
@ -150,9 +151,9 @@ public struct Tokenizer {
|
|||
return StructDeclaration(
|
||||
name: name,
|
||||
accessibility: accessibility,
|
||||
range: range!,
|
||||
nameRange: nameRange!,
|
||||
bodyRange: bodyRange!,
|
||||
// range: range!,
|
||||
// nameRange: nameRange!,
|
||||
// bodyRange: bodyRange!,
|
||||
attributes: attributes,
|
||||
children: children
|
||||
)
|
||||
|
@ -172,7 +173,7 @@ public struct Tokenizer {
|
|||
)
|
||||
|
||||
case Kinds.InstanceVariable.rawValue:
|
||||
let setterAccessibility = (dictionary[Key.SetterAccessibility.rawValue] as? String).flatMap(Accessibility.init)
|
||||
let setterAccessibility = (dictionary[Key.SetterAccessibility.rawValue] as? String).flatMap(Accessibility.init(string:))
|
||||
|
||||
if String(source.utf8.dropFirst(range!.startIndex))?.takeUntil(occurence: name)?.trimmed.hasPrefix("let") == true {
|
||||
return nil
|
||||
|
@ -207,9 +208,9 @@ public struct Tokenizer {
|
|||
returnSignature = parseReturnSignature(source: source.utf8[nameRange!.endIndex..<range!.endIndex].trimmed)
|
||||
}
|
||||
|
||||
// methods can specify an empty public name of a parameter without any private name - `fun(_: String)`
|
||||
// methods can specify an empty name of a parameter without any private name - `fun(_: String)`
|
||||
let namedParameters = parameters.enumerated().map { index, parameter -> MethodParameter in
|
||||
if parameter.name == Tokenizer.nameNotSet {
|
||||
if parameter.name == Self.nameNotSet {
|
||||
var mutableParameter = parameter
|
||||
mutableParameter.name = "parameter\(index)"
|
||||
return mutableParameter
|
||||
|
@ -239,8 +240,8 @@ public struct Tokenizer {
|
|||
name: name,
|
||||
accessibility: accessibility,
|
||||
returnSignature: returnSignature,
|
||||
range: range!,
|
||||
nameRange: nameRange!,
|
||||
// range: range!,
|
||||
// nameRange: nameRange!,
|
||||
parameters: namedParameters,
|
||||
attributes: attributes,
|
||||
genericParameters: fixedGenericParameters
|
||||
|
@ -265,8 +266,8 @@ public struct Tokenizer {
|
|||
let fullRange = range.lowerBound..<(range.upperBound + inheritanceMatch.range.length)
|
||||
return GenericParameter(
|
||||
name: name,
|
||||
range: fullRange,
|
||||
inheritedType: InheritanceDeclaration(name: inheritance)
|
||||
// range: fullRange,
|
||||
inheritedType: inheritance
|
||||
)
|
||||
|
||||
default:
|
||||
|
@ -297,8 +298,8 @@ public struct Tokenizer {
|
|||
private func tokenize(parameterLabel: String?, parameter: SourceKitRepresentable) -> Token? {
|
||||
guard let dictionary = parameter as? [String: SourceKitRepresentable] else { return nil }
|
||||
|
||||
let name = dictionary[Key.Name.rawValue] as? String ?? Tokenizer.nameNotSet
|
||||
let kind = dictionary[Key.Kind.rawValue] as? String ?? Tokenizer.unknownType
|
||||
let name = dictionary[Key.Name.rawValue] as? String ?? Self.nameNotSet
|
||||
let kind = dictionary[Key.Kind.rawValue] as? String ?? Self.unknownType
|
||||
let range = extractRange(from: dictionary, offset: .Offset, length: .Length)
|
||||
let nameRange = extractRange(from: dictionary, offset: .NameOffset, length: .NameLength)
|
||||
let type = dictionary[Key.TypeName.rawValue] as? String
|
||||
|
@ -328,7 +329,12 @@ public struct Tokenizer {
|
|||
|
||||
let wrappableType = WrappableType(parsing: inoutSeparatedType)
|
||||
|
||||
return MethodParameter(label: parameterLabel, name: name, type: wrappableType, range: range!, nameRange: nameRange, isInout: isInout)
|
||||
return MethodParameter(
|
||||
label: parameterLabel,
|
||||
name: name,
|
||||
type: wrappableType,
|
||||
isInout: isInout
|
||||
)
|
||||
|
||||
case Kinds.GenericParameter.rawValue:
|
||||
let inheritedTypeElement = (dictionary[Key.InheritedTypes.rawValue] as? [SourceKitRepresentable] ?? []).first
|
||||
|
@ -375,7 +381,7 @@ public struct Tokenizer {
|
|||
.map { result -> Import in
|
||||
let range = result.range.location..<(result.range.location + result.range.length)
|
||||
let library = source.stringMatch(from: result, at: 1)
|
||||
return Import(range: range, importee: .library(name: library))
|
||||
return Import(range: range, kind: .library(name: library))
|
||||
}
|
||||
let components = componentRegex.matches(in: source, range: NSRange(location: 0, length: source.count))
|
||||
.filter { result in
|
||||
|
@ -387,7 +393,7 @@ public struct Tokenizer {
|
|||
let library = source[result.range(at: 2)]
|
||||
let component = source[result.range(at: 3)]
|
||||
let range = result.range.location..<(result.range.location + result.range.length)
|
||||
return Import(range: range, importee: .component(componentType: componentType, library: library, name: component))
|
||||
return Import(range: range, kind: .component(componentType: componentType, library: library, name: component))
|
||||
}
|
||||
|
||||
return libraries + components
|
||||
|
@ -515,7 +521,12 @@ public struct Tokenizer {
|
|||
index = source.index(after: index)
|
||||
}
|
||||
|
||||
return ReturnSignature(isAsync: isAsync, throwString: throwString, returnType: returnType ?? WrappableType.type("Void"), whereConstraints: whereConstraints)
|
||||
return ReturnSignature(
|
||||
asyncType: isAsync ? .async : nil,
|
||||
throwType: throwString.flatMap(ThrowType.init(string:)),
|
||||
returnType: returnType ?? WrappableType.type("Void"),
|
||||
whereConstraints: whereConstraints
|
||||
)
|
||||
}
|
||||
|
||||
// FIXME: Remove when SourceKitten fixes the off-by-one error that includes the ending `>` in the last inherited type.
|
||||
|
@ -539,29 +550,10 @@ public struct Tokenizer {
|
|||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
subscript(range: NSRange) -> String {
|
||||
let fromIndex = self.index(self.startIndex, offsetBy: range.location)
|
||||
let toIndex = self.index(fromIndex, offsetBy: range.length)
|
||||
return String(self[fromIndex..<toIndex])
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
func stringMatch(from match: NSTextCheckingResult, at range: Int = 0) -> String {
|
||||
let matchRange = match.range(at: range)
|
||||
let fromIndex = index(startIndex, offsetBy: matchRange.location)
|
||||
let toIndex = index(fromIndex, offsetBy: matchRange.length)
|
||||
return String(self[fromIndex..<toIndex])
|
||||
}
|
||||
|
||||
func removing(match: NSTextCheckingResult, at range: Int = 0) -> String {
|
||||
let matchRange = match.range(at: range)
|
||||
let fromIndex = index(startIndex, offsetBy: matchRange.location)
|
||||
let toIndex = index(fromIndex, offsetBy: matchRange.length)
|
||||
|
||||
var mutableString = self
|
||||
mutableString.removeSubrange(fromIndex..<toIndex)
|
||||
return mutableString
|
||||
}
|
||||
private(set) var stderrUsed = false
|
||||
|
||||
func stderrPrint(_ item: Any) {
|
||||
stderrUsed = true
|
||||
fputs("error: \(item)\n", stderr)
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,3 @@
|
|||
//{{ start }}
|
||||
// {{ content }}
|
||||
//{{ end }}
|
|
@ -0,0 +1,129 @@
|
|||
import Foundation
|
||||
|
||||
extension Templates {
|
||||
static let staticGenericParameter = "_CUCKOO$$GENERIC"
|
||||
static let typeErasureClassName = "DefaultImplCaller"
|
||||
static let mock = """
|
||||
{% for container in containers %}
|
||||
{% if debug %}
|
||||
// {{ container }}
|
||||
{% endif %}
|
||||
{% for attribute in container.attributes %}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
{% if container.hasParent %}
|
||||
extension {{ container.parentFullyQualifiedName }} {
|
||||
{% endif %}
|
||||
{{ container.accessibility|withSpace }}class {{ container.mockName }}{{ container.genericParameters }}:{% if container.isNSObjectProtocol %} NSObject,{% endif %} {{ container.name }}{% if container.isImplementation %}{{ container.genericArguments }}{% endif %},{% if container.isImplementation %} Cuckoo.ClassMock{% else %} Cuckoo.ProtocolMock{% endif %} {
|
||||
{% if container.isGeneric and not container.isImplementation %}
|
||||
{{ container.accessibility|withSpace }}typealias MocksType = \(typeErasureClassName){{ container.genericArguments }}
|
||||
{% else %}
|
||||
{{ container.accessibility|withSpace }}typealias MocksType = {{ container.name }}{{ container.genericArguments }}
|
||||
{% endif %}
|
||||
{{ container.accessibility|withSpace }}typealias Stubbing = __StubbingProxy_{{ container.name }}
|
||||
{{ container.accessibility|withSpace }}typealias Verification = __VerificationProxy_{{ container.name }}
|
||||
|
||||
{{ container.accessibility|withSpace }}let cuckoo_manager = Cuckoo.MockManager.preconfiguredManager ?? Cuckoo.MockManager(hasParent: {{ container.isImplementation }})
|
||||
|
||||
{% if container.isGeneric and not container.isImplementation %}
|
||||
\(Templates.typeErasure.indented())
|
||||
|
||||
private var __defaultImplStub: \(typeErasureClassName){{ container.genericArguments }}?
|
||||
|
||||
{{ container.accessibility|withSpace }}func enableDefaultImplementation<\(staticGenericParameter): {{ container.name }}>(_ stub: \(staticGenericParameter)) where {{ container.genericProtocolIdentity }} {
|
||||
var mutableStub = stub
|
||||
__defaultImplStub = \(typeErasureClassName)(from: &mutableStub, keeping: mutableStub)
|
||||
cuckoo_manager.enableDefaultStubImplementation()
|
||||
}
|
||||
|
||||
{{ container.accessibility|withSpace }}func enableDefaultImplementation<\(staticGenericParameter): {{ container.name }}>(mutating stub: UnsafeMutablePointer<\(staticGenericParameter)>) where {{ container.genericProtocolIdentity }} {
|
||||
__defaultImplStub = \(typeErasureClassName)(from: stub, keeping: nil)
|
||||
cuckoo_manager.enableDefaultStubImplementation()
|
||||
}
|
||||
{% else %}
|
||||
private var __defaultImplStub: {{ container.name }}{{ container.genericArguments }}?
|
||||
|
||||
{{ container.accessibility|withSpace }}func enableDefaultImplementation(_ stub: {{ container.name }}{{ container.genericArguments }}) {
|
||||
__defaultImplStub = stub
|
||||
cuckoo_manager.enableDefaultStubImplementation()
|
||||
}
|
||||
{% endif -%}
|
||||
|
||||
{% for property in container.properties %}
|
||||
{% if debug %}
|
||||
// {{property}}
|
||||
{% endif %}
|
||||
{% for attribute in property.attributes %}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
{{ property.accessibility|withSpace }}{% if property.isOverriding %}override {% endif %} var {{ property.name }}: {{ property.type }} {
|
||||
get {
|
||||
return cuckoo_manager.getter(
|
||||
"{{ property.name }}",
|
||||
superclassCall: {%+ if container.isImplementation -%}
|
||||
super.{{ property.name }}
|
||||
{%- else -%}
|
||||
Cuckoo.MockManager.crashOnProtocolSuperclassCall()
|
||||
{%- endif -%},
|
||||
defaultCall: __defaultImplStub!.{{property.name}}
|
||||
)
|
||||
}
|
||||
{% ifnot property.isReadOnly %}
|
||||
set {
|
||||
cuckoo_manager.setter(
|
||||
"{{ property.name }}",
|
||||
value: newValue,
|
||||
superclassCall: {%+ if container.isImplementation -%}
|
||||
super.{{ property.name }} = newValue
|
||||
{%- else -%}
|
||||
Cuckoo.MockManager.crashOnProtocolSuperclassCall()
|
||||
{%- endif -%},
|
||||
defaultCall: __defaultImplStub!.{{property.name}} = newValue)
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
{% for initializer in container.initializers %}
|
||||
{% if debug %}
|
||||
// {{initializer}}
|
||||
{% endif %}
|
||||
{{ initializer.accessibility|withSpace }}required init{{initializer.signature}} {}
|
||||
{% endfor %}
|
||||
|
||||
{% for method in container.methods %}
|
||||
{% if debug %}
|
||||
// {{method}}
|
||||
{% endif %}
|
||||
{% for attribute in method.attributes %}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
{{ method.accessibility|withSpace }}{% if method.isOverriding %}override {%+ endif %}func {{ method.name|escapeReservedKeywords }}{{ method.signature }} {
|
||||
{{ method.self|openNestedClosure }}
|
||||
return{% if method.isThrowing %} try{% endif %}{% if method.isAsync %} await{% endif %} cuckoo_manager.call{% if method.isThrowing %}{{ method.throwType|capitalize }}{% endif %}(
|
||||
\"\"\"
|
||||
{{method.fullyQualifiedName}}
|
||||
\"\"\",
|
||||
parameters: ({{method.parameterNames}}),
|
||||
escapingParameters: ({{method.escapingParameterNames}}),
|
||||
superclassCall: {%+ if container.isImplementation %}{% if method.isAsync %}await {%+ endif %}super.{{method.name}}({{method.call}}){% else %}Cuckoo.MockManager.crashOnProtocolSuperclassCall(){% endif %},
|
||||
defaultCall: {%+ if method.isAsync %}await {%+ endif %}__defaultImplStub!.{{method.name}}{%if method.isOptional %}!{%endif%}({{method.call}})
|
||||
)
|
||||
{{ method.parameters|closeNestedClosure }}
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
\(Templates.stubbingProxy.indented())
|
||||
|
||||
\(Templates.verificationProxy.indented())
|
||||
}
|
||||
|
||||
\(Templates.noImplStub)
|
||||
|
||||
{% if container.hasParent %}
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
"""
|
||||
}
|
|
@ -1,23 +1,23 @@
|
|||
extension Templates {
|
||||
static let noImplStub = """
|
||||
{% for attribute in container.attributes %}
|
||||
{{ attribute.text }}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
{{container.accessibility}} class {{ container.name }}Stub{{ container.genericParameters }}: {% if container.isNSObjectProtocol %}NSObject, {% endif %}{{ container.name }}{% if container.isImplementation %}{{ container.genericArguments }}{% endif %} {
|
||||
{{container.accessibility|withSpace}}class {{ container.name }}Stub{{ container.genericParameters }}: {% if container.isNSObjectProtocol %}NSObject, {% endif %}{{ container.name }}{% if container.isImplementation %}{{ container.genericArguments }}{% endif %} {
|
||||
{% for property in container.properties %}
|
||||
{{ property.unavailablePlatformsCheck }}
|
||||
{% if debug %}
|
||||
// {{property}}
|
||||
{% endif %}
|
||||
{% for attribute in property.attributes %}
|
||||
{{ attribute.text }}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
{{ property.accessibility }}{% if container.@type == "ClassDeclaration" %} override{% endif %} var {{ property.name }}: {{ property.type }} {
|
||||
{{ property.accessibility|withSpace }}{% if property.isOverriding %}override{% endif %} var {{ property.name }}: {{ property.type }} {
|
||||
get {
|
||||
return DefaultValueRegistry.defaultValue(for: ({{property.type|genericSafe|removeClosureArgumentNames}}).self)
|
||||
}
|
||||
{% ifnot property.isReadOnly %}
|
||||
set { }
|
||||
set {}
|
||||
{% endif %}
|
||||
}
|
||||
{% if property.hasUnavailablePlatforms %}
|
||||
|
@ -27,11 +27,7 @@ extension Templates {
|
|||
|
||||
{% for initializer in container.initializers %}
|
||||
{{ initializer.unavailablePlatformsCheck }}
|
||||
{{ initializer.accessibility }}{% if container.@type == "ClassDeclaration" %} override{% endif %}{% if initializer.@type == "ProtocolMethod" %} required{%endif%} init({{initializer.parameterSignature}}) {
|
||||
{% if container.@type == "ClassDeclaration" %}
|
||||
super.init({{initializer.call}})
|
||||
{% endif %}
|
||||
}
|
||||
{{ initializer.accessibility|withSpace }}required init{{initializer.signature}} {}
|
||||
{% if initializer.hasUnavailablePlatforms %}
|
||||
#endif
|
||||
{% endif %}
|
||||
|
@ -43,9 +39,9 @@ extension Templates {
|
|||
// {{method}}
|
||||
{% endif %}
|
||||
{% for attribute in method.attributes %}
|
||||
{{ attribute.text }}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
{{ method.accessibility }}{% if container.@type == "ClassDeclaration" and method.isOverriding %} override{% endif %} func {{ method.name|escapeReservedKeywords }}{{ method.genericParameters }}({{ method.parameterSignature }}) {{ method.returnSignature }} {{ method.whereClause }} {
|
||||
{{ method.accessibility|withSpace }}{% if method.isOverriding %}override{% endif %} func {{ method.name|escapeReservedKeywords }}{{ method.signature }} {
|
||||
return DefaultValueRegistry.defaultValue(for: ({{method.returnType|genericSafe}}).self)
|
||||
}
|
||||
{% if method.hasUnavailablePlatforms %}
|
|
@ -2,16 +2,16 @@ import Foundation
|
|||
|
||||
extension Templates {
|
||||
static let stubbingProxy = """
|
||||
{{ container.accessibility }} struct __StubbingProxy_{{ container.name }}: Cuckoo.StubbingProxy {
|
||||
{{ container.accessibility|withSpace }}struct __StubbingProxy_{{ container.name }}: Cuckoo.StubbingProxy {
|
||||
private let cuckoo_manager: Cuckoo.MockManager
|
||||
|
||||
{{ container.accessibility }} init(manager: Cuckoo.MockManager) {
|
||||
{{ container.accessibility|withSpace }}init(manager: Cuckoo.MockManager) {
|
||||
self.cuckoo_manager = manager
|
||||
}
|
||||
{% for property in container.properties %}
|
||||
{{ property.unavailablePlatformsCheck }}
|
||||
{% for attribute in property.attributes %}
|
||||
{{ attribute.text }}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
var {{property.name}}: Cuckoo.{{ property.stubType }}<{{ container.mockName }}, {% if property.isReadOnly %}{{property.type|genericSafe}}{% else %}{{property.nonOptionalType|genericSafe}}{% endif %}> {
|
||||
return .init(manager: cuckoo_manager, name: "{{property.name}}")
|
||||
|
@ -23,14 +23,16 @@ extension Templates {
|
|||
{% for method in container.methods %}
|
||||
{{ method.unavailablePlatformsCheck }}
|
||||
{% for attribute in method.attributes %}
|
||||
{{ attribute.text }}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
func {{method.name|escapeReservedKeywords}}{{method.self|matchableGenericNames}}({{method.parameters|matchableParameterSignature}}) -> {{method.stubFunction}}<({{method.inputTypes|genericSafe}}){%if method.returnType != "Void" %}, {{method.returnType|genericSafe}}{%endif%}>{{method.self|matchableGenericWhereClause}} {
|
||||
{{method.parameters|parameterMatchers}}
|
||||
return .init(stub: cuckoo_manager.createStub(for: {{ container.mockName }}.self, method:
|
||||
\"\"\"
|
||||
{{method.fullyQualifiedName}}
|
||||
\"\"\", parameterMatchers: matchers))
|
||||
return .init(stub: cuckoo_manager.createStub(for: {{ container.mockName }}.self,
|
||||
method: \"\"\"
|
||||
{{method.fullyQualifiedName}}
|
||||
\"\"\",
|
||||
parameterMatchers: matchers
|
||||
))
|
||||
}
|
||||
{% if method.hasUnavailablePlatforms %}
|
||||
#endif
|
|
@ -2,14 +2,19 @@ import Foundation
|
|||
|
||||
extension Templates {
|
||||
static let typeErasure = """
|
||||
{{ container.accessibility }} class \(typeErasureClassName){{ container.genericParameters }}: {{ container.name }} {
|
||||
{{ container.accessibility|withSpace }}class \(typeErasureClassName){{ container.genericParameters }}: {{ container.name }} {
|
||||
private let reference: Any
|
||||
|
||||
{% for property in container.properties %}private let _getter_storage$${{ property.name }}: () -> {{ property.type }}{% if not property.isReadOnly %}
|
||||
private let _setter_storage$${{ property.name }}: ({{ property.type }}) -> Void{% endif %}
|
||||
{{ container.accessibility }} var {{ property.name }}: {{ property.type }} {
|
||||
get { return _getter_storage$${{ property.name }}() }{% if not property.isReadOnly %}
|
||||
set { _setter_storage$${{ property.name }}(newValue) }{% endif %}
|
||||
{% for property in container.properties %}
|
||||
private let _getter_storage$${{ property.name }}: () -> {{ property.type }}
|
||||
{% if not property.isReadOnly %}
|
||||
private let _setter_storage$${{ property.name }}: ({{ property.type }}) -> Void
|
||||
{% endif %}
|
||||
{{ container.accessibility|withSpace }}var {{ property.name }}: {{ property.type }} {
|
||||
get { return _getter_storage$${{ property.name }}() }
|
||||
{% if not property.isReadOnly %}
|
||||
set { _setter_storage$${{ property.name }}(newValue) }
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
{% endfor %}
|
||||
|
@ -18,22 +23,28 @@ extension Templates {
|
|||
init<\(staticGenericParameter): {{ container.name }}>(from defaultImpl: UnsafeMutablePointer<\(staticGenericParameter)>, keeping reference: @escaping @autoclosure () -> Any?) where {{ container.genericProtocolIdentity }} {
|
||||
self.reference = reference
|
||||
|
||||
{% for property in container.properties %}_getter_storage$${{ property.name }} = { defaultImpl.pointee.{{ property.name }} }
|
||||
{% if not property.isReadOnly %}_setter_storage$${{ property.name }} = { defaultImpl.pointee.{{ property.name }} = $0 }{% endif %}
|
||||
{% for property in container.properties %}
|
||||
_getter_storage$${{ property.name }} = { defaultImpl.pointee.{{ property.name }} }
|
||||
{% if not property.isReadOnly %}
|
||||
_setter_storage$${{ property.name }} = { defaultImpl.pointee.{{ property.name }} = $0 }
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for method in container.methods %}_storage${{ forloop.counter }}${{ method.name }} = defaultImpl.pointee.{{ method.name }}
|
||||
{% for method in container.methods %}
|
||||
_storage${{ forloop.counter }}${{ method.name }} = defaultImpl.pointee.{{ method.name }}
|
||||
{% endfor %}
|
||||
}
|
||||
{% if container.initializers %}
|
||||
/// MARK:- ignored required initializers{% endif %}
|
||||
{% for initializer in container.initializers %}{{ container.accessibility }} required init({{ initializer.parameterSignature }}) {
|
||||
/// MARK:- ignored required initializers
|
||||
{% endif %}
|
||||
{% for initializer in container.initializers %}
|
||||
{{ container.accessibility|withSpace }}required init{{initializer.signature}} {
|
||||
fatalError("`DefaultImplCaller` class is only used for calling default implementation and can't be initialized on its own.")
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
{% for method in container.methods %}
|
||||
{% for method in container.methods +%}
|
||||
private let _storage${{ forloop.counter }}${{ method.name }}: ({{ method.inputTypes }}) {% if method.isAsync %} async{% endif %} -> {{ method.returnType }}
|
||||
{{ container.accessibility }} func {{ method.name|escapeReservedKeywords }}({{ method.parameterSignature }}) {{ method.returnSignature }} {
|
||||
{{ container.accessibility|withSpace }}func {{ method.name|escapeReservedKeywords }}{{ method.signature }} {
|
||||
return {% if method.isAsync %} await{% endif %} _storage${{ forloop.counter }}${{ method.name }}({{ method.parameterNames }})
|
||||
}
|
||||
{% endfor %}
|
|
@ -2,42 +2,42 @@ import Foundation
|
|||
|
||||
extension Templates {
|
||||
static let verificationProxy = """
|
||||
{{ container.accessibility }} struct __VerificationProxy_{{ container.name }}: Cuckoo.VerificationProxy {
|
||||
{{ container.accessibility|withSpace }}struct __VerificationProxy_{{ container.name }}: Cuckoo.VerificationProxy {
|
||||
private let cuckoo_manager: Cuckoo.MockManager
|
||||
private let callMatcher: Cuckoo.CallMatcher
|
||||
private let sourceLocation: Cuckoo.SourceLocation
|
||||
|
||||
{{ container.accessibility }} init(manager: Cuckoo.MockManager, callMatcher: Cuckoo.CallMatcher, sourceLocation: Cuckoo.SourceLocation) {
|
||||
{{ container.accessibility|withSpace }}init(manager: Cuckoo.MockManager, callMatcher: Cuckoo.CallMatcher, sourceLocation: Cuckoo.SourceLocation) {
|
||||
self.cuckoo_manager = manager
|
||||
self.callMatcher = callMatcher
|
||||
self.sourceLocation = sourceLocation
|
||||
}
|
||||
|
||||
{% for property in container.properties %}
|
||||
{{ property.unavailablePlatformsCheck }}
|
||||
{% for attribute in property.attributes %}
|
||||
{{ attribute.text }}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
var {{property.name}}: Cuckoo.{{property.verifyType}}<{% if property.isReadOnly %}{{property.type|genericSafe}}{% else %}{{property.nonOptionalType|genericSafe}}{% endif %}> {
|
||||
return .init(manager: cuckoo_manager, name: "{{property.name}}", callMatcher: callMatcher, sourceLocation: sourceLocation)
|
||||
}
|
||||
{% if property.hasUnavailablePlatforms %}
|
||||
#endif
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% for method in container.methods %}
|
||||
{{ method.unavailablePlatformsCheck }}
|
||||
{% for attribute in method.attributes %}
|
||||
{{ attribute.text }}
|
||||
{{ attribute }}
|
||||
{% endfor %}
|
||||
@discardableResult
|
||||
func {{method.name|escapeReservedKeywords}}{{method.self|matchableGenericNames}}({{method.parameters|matchableParameterSignature}}) -> Cuckoo.__DoNotUse<({{method.inputTypes|genericSafe}}), {{method.returnType|genericSafe}}>{{method.self|matchableGenericWhereClause}} {
|
||||
{{method.parameters|parameterMatchers}}
|
||||
return cuckoo_manager.verify(
|
||||
\"\"\"
|
||||
{{method.fullyQualifiedName}}
|
||||
\"\"\", callMatcher: callMatcher, parameterMatchers: matchers, sourceLocation: sourceLocation)
|
||||
\"\"\"
|
||||
{{method.fullyQualifiedName}}
|
||||
\"\"\",
|
||||
callMatcher: callMatcher,
|
||||
parameterMatchers: matchers,
|
||||
sourceLocation: sourceLocation
|
||||
)
|
||||
}
|
||||
{% if method.hasUnavailablePlatforms %}
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
import SwiftSyntax
|
||||
|
||||
enum Accessibility: String, Equatable {
|
||||
case `open`
|
||||
case `public`
|
||||
case `internal`
|
||||
case `private`
|
||||
case `fileprivate`
|
||||
|
||||
var sourceName: String {
|
||||
switch self {
|
||||
case .open:
|
||||
fallthrough
|
||||
case .public:
|
||||
return "public"
|
||||
case .internal:
|
||||
return ""
|
||||
case .private:
|
||||
return "private"
|
||||
case .fileprivate:
|
||||
return "fileprivate"
|
||||
}
|
||||
}
|
||||
|
||||
var isAccessible: Bool {
|
||||
self != .private && self != .fileprivate
|
||||
}
|
||||
}
|
||||
|
||||
extension Accessibility {
|
||||
init?(tokenKind: TokenKind) {
|
||||
switch tokenKind {
|
||||
case .publicKeyword:
|
||||
self = .public
|
||||
case .internalKeyword:
|
||||
self = .internal
|
||||
case .privateKeyword:
|
||||
self = .private
|
||||
case .fileprivateKeyword:
|
||||
self = .fileprivate
|
||||
case .identifier("open"):
|
||||
self = .open
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Accessibility: Comparable {
|
||||
static func < (lhs: Accessibility, rhs: Accessibility) -> Bool {
|
||||
lhs.openness < rhs.openness
|
||||
}
|
||||
|
||||
/// How open is this accessibility. The higher number the more accessible.
|
||||
private var openness: Int {
|
||||
switch self {
|
||||
case .open:
|
||||
return 4
|
||||
case .public:
|
||||
return 3
|
||||
case .internal:
|
||||
return 2
|
||||
case .fileprivate:
|
||||
return 1
|
||||
case .private:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
enum AsyncType: String, CustomStringConvertible, Equatable {
|
||||
case `async`
|
||||
case `reasync`
|
||||
|
||||
var isAsync: Bool {
|
||||
self == .async
|
||||
}
|
||||
|
||||
var isReasync: Bool {
|
||||
self == .reasync
|
||||
}
|
||||
|
||||
var description: String {
|
||||
rawValue
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import Foundation
|
||||
|
||||
enum Attribute: Hashable, CustomStringConvertible {
|
||||
case available(arguments: [String])
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .available(let arguments):
|
||||
return "@available(\(arguments.joined(separator: ", ")))"
|
||||
}
|
||||
}
|
||||
|
||||
var unavailablePlatform: String? {
|
||||
guard case .available(let arguments) = self,
|
||||
arguments.count == 2,
|
||||
arguments[1] == "unavailable" else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return String(arguments[0])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
protocol HasAccessibility: Token {
|
||||
var accessibility: Accessibility { get set }
|
||||
}
|
||||
|
||||
extension HasAccessibility {
|
||||
var areAllHierarchiesAccessible: Bool {
|
||||
guard accessibility.isAccessible else { return false }
|
||||
var parent: Token? = parent?.value
|
||||
while let p = parent as? HasAccessibility {
|
||||
guard p.accessibility.isAccessible else { return false }
|
||||
parent = p.parent?.value
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
protocol HasAttributes: Token {
|
||||
var attributes: [Attribute] { get }
|
||||
}
|
||||
|
||||
extension HasAttributes {
|
||||
private var unavailablePlatforms: [String] {
|
||||
attributes.compactMap { $0.unavailablePlatform }
|
||||
}
|
||||
|
||||
var hasUnavailablePlatforms: Bool {
|
||||
!unavailablePlatforms.isEmpty
|
||||
}
|
||||
|
||||
var unavailablePlatformsCheck: String {
|
||||
hasUnavailablePlatforms ? "#if !os(\(unavailablePlatforms.joined(separator: ") && !os(")))" : ""
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
protocol HasGenerics: Token {
|
||||
var genericParameters: [GenericParameter] { get }
|
||||
var genericRequirements: [String] { get }
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
protocol HasInheritance: Token {
|
||||
var inheritedTypes: [String] { get }
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
protocol HasMembers: Token {
|
||||
var members: [Token] { get set }
|
||||
|
||||
func replacing(members: [Token]) -> Self
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
protocol HasName: Token {
|
||||
var name: String { get }
|
||||
}
|
||||
|
||||
extension HasName {
|
||||
var mockName: String {
|
||||
"Mock\(name)"
|
||||
}
|
||||
|
||||
var fullyQualifiedName: String {
|
||||
var names = [name]
|
||||
var parent: Token? = parent?.value
|
||||
while let p = parent as? HasName {
|
||||
names.insert(p.name, at: 0)
|
||||
parent = p.parent?.value
|
||||
}
|
||||
return names.joined(separator: ".")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import Foundation
|
||||
|
||||
//protocol ChildToken: Token {
|
||||
//
|
||||
//}
|
|
@ -0,0 +1,24 @@
|
|||
struct ClassDeclaration: ContainerToken {
|
||||
var parent: Reference<Token>?
|
||||
|
||||
var attributes: [Attribute]
|
||||
var accessibility: Accessibility
|
||||
var name: String
|
||||
var genericParameters: [GenericParameter]
|
||||
var genericRequirements: [String]
|
||||
var inheritedTypes: [String]
|
||||
var members: [Token]
|
||||
|
||||
func replacing(members: [Token]) -> ClassDeclaration {
|
||||
ClassDeclaration(
|
||||
parent: parent,
|
||||
attributes: attributes,
|
||||
accessibility: accessibility,
|
||||
name: name,
|
||||
genericParameters: genericParameters,
|
||||
genericRequirements: genericRequirements,
|
||||
inheritedTypes: inheritedTypes,
|
||||
members: members
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
protocol ContainerToken: Token, HasAttributes, HasAccessibility, HasName, HasGenerics, HasMembers, HasInheritance {}
|
||||
|
||||
extension ContainerToken {
|
||||
func containerSerialize() -> GeneratorContext {
|
||||
func withAdjustedAccessibility<TokenType: HasAccessibility>(token: TokenType) -> TokenType {
|
||||
// We only want to adjust tokens that are accessible and lower than the enclosing type
|
||||
guard token.accessibility.isAccessible && token.accessibility < accessibility else { return token }
|
||||
var mutableToken = token
|
||||
mutableToken.accessibility = accessibility
|
||||
return mutableToken
|
||||
}
|
||||
|
||||
let accessibilityAdjustedMembers = members.map { child -> Token in
|
||||
guard let memberWithAccessibility = child as? Token & HasAccessibility else { return child }
|
||||
return withAdjustedAccessibility(token: memberWithAccessibility)
|
||||
}
|
||||
|
||||
let properties = accessibilityAdjustedMembers.compactMap { $0 as? Variable }
|
||||
.filter { $0.accessibility.isAccessible }
|
||||
.map { $0.serialize() }
|
||||
|
||||
let methods = accessibilityAdjustedMembers.compactMap { $0 as? Method }
|
||||
.filter { $0.accessibility.isAccessible }
|
||||
.map { $0.serialize() }
|
||||
|
||||
let initializers = accessibilityAdjustedMembers.compactMap { $0 as? Initializer }
|
||||
.filter { $0.accessibility.isAccessible }
|
||||
.map { $0.serialize() }
|
||||
|
||||
return [
|
||||
"accessibility": accessibility.sourceName,
|
||||
// "isAccessible": accessibility.isAccessible,
|
||||
// "children": accessibilityAdjustedMembers.map { $0.serialize() },
|
||||
"properties": properties,
|
||||
"initializers": isClass ? [] : initializers,
|
||||
"methods": methods,
|
||||
"attributes": attributes,
|
||||
]
|
||||
.compactMapValues { $0 }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
struct Deinitializer: Token, HasAttributes {
|
||||
var parent: Reference<Token>?
|
||||
|
||||
var attributes: [Attribute]
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
import Foundation
|
||||
import FileKit
|
||||
|
||||
struct FileRepresentation {
|
||||
let file: TextFile
|
||||
let imports: [Import]
|
||||
let tokens: [Token]
|
||||
|
||||
init(file: TextFile, imports: [Import], tokens: [Token]) {
|
||||
self.file = file
|
||||
self.imports = imports
|
||||
self.tokens = tokens
|
||||
}
|
||||
|
||||
func replacing(tokens: [Token]) -> FileRepresentation {
|
||||
FileRepresentation(file: file, imports: imports, tokens: tokens)
|
||||
}
|
||||
}
|
||||
|
||||
extension FileRepresentation {
|
||||
func mergingInheritance(with files: [FileRepresentation]) -> FileRepresentation {
|
||||
let mergedTokens = tokens.reduce([] as [Token]) { list, token in
|
||||
let mergeToken = token.mergingInheritance(with: files)
|
||||
return list + [mergeToken]
|
||||
}
|
||||
return replacing(tokens: mergedTokens)
|
||||
}
|
||||
|
||||
func inheritNSObject(protocols: [ProtocolDeclaration]) -> FileRepresentation {
|
||||
replacing(tokens: tokens.map { $0.inheritingNSObject(protocols: protocols) })
|
||||
}
|
||||
|
||||
func flatMappingMemberContainers() -> FileRepresentation {
|
||||
replacing(tokens: tokens.flatMap { $0.flatMappingMemberContainers() })
|
||||
}
|
||||
}
|
||||
|
||||
extension Token {
|
||||
// TODO: This would be much better as a dictionary instead of going through all the files for every inheritance type.
|
||||
private static func findToken(forClassOrProtocol name: String, in files: [FileRepresentation]) -> Token? {
|
||||
files.lazy
|
||||
.flatMap { $0.tokens }
|
||||
.filter { $0.isClass || $0.isProtocol }
|
||||
.compactMap { $0 as? HasName }
|
||||
.first { $0.name == name }
|
||||
}
|
||||
|
||||
fileprivate func mergingInheritance(with files: [FileRepresentation]) -> Token {
|
||||
guard let token = self as? Token & HasMembers & HasInheritance else { return self }
|
||||
|
||||
let inheritedRepresentations = token.inheritedTypes
|
||||
.compactMap { Self.findToken(forClassOrProtocol: $0, in: files) }
|
||||
.compactMap { $0.mergingInheritance(with: files) }
|
||||
|
||||
let mergedTokens = inheritedRepresentations
|
||||
.compactMap { $0 as? HasMembers }
|
||||
.flatMap { $0.members }
|
||||
.reduce(token.members) { tokens, inheritedToken in
|
||||
if let inheritedInheritable = inheritedToken as? Inheritable,
|
||||
tokens.compactMap({ $0 as? Inheritable }).contains(where: { $0.isEqual(to: inheritedInheritable) }) {
|
||||
return tokens
|
||||
} else {
|
||||
return tokens + [inheritedToken]
|
||||
}
|
||||
}
|
||||
|
||||
switch token {
|
||||
case let classToken as ClassDeclaration:
|
||||
return classToken.replacing(members: mergedTokens)
|
||||
case let protocolToken as ProtocolDeclaration:
|
||||
return protocolToken.replacing(members: mergedTokens)
|
||||
default:
|
||||
assertionFailure("This case should not be possible.")
|
||||
return token
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func inheritingNSObject(protocols: [ProtocolDeclaration]) -> Token {
|
||||
guard let protocolToken = self as? ProtocolDeclaration, !protocolToken.isNSObjectProtocol else { return self }
|
||||
return protocols.contains { $0.name == protocolToken.name } ? protocolToken.replacing(isNSObjectProtocol: true) : self
|
||||
}
|
||||
}
|
||||
|
||||
extension Token {
|
||||
fileprivate func flatMappingMemberContainers() -> [Token] {
|
||||
guard let selfHasMembers = self as? HasMembers else { return [self] }
|
||||
return [self] + selfHasMembers.members.flatMap { token in
|
||||
if let hasMembers = token as? HasMembers {
|
||||
return hasMembers.flatMappingMemberContainers()
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import Foundation
|
||||
|
||||
struct GenericParameter: Equatable {
|
||||
let name: String
|
||||
let inheritedTypes: [String]
|
||||
|
||||
var description: String {
|
||||
if inheritedTypes.isEmpty {
|
||||
return name
|
||||
} else {
|
||||
return "\(name): \(inheritedTypes.joined(separator: " & "))"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element == GenericParameter {
|
||||
var sourceDescription: String {
|
||||
"<\(map { $0.description }.joined(separator: ", "))>"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
enum Import: Hashable, CustomStringConvertible {
|
||||
case library(name: String)
|
||||
case component(kind: String, name: String)
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .library(let name):
|
||||
return name
|
||||
case .component(let kind, let name):
|
||||
return "\(kind) \(name)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//extension Import: Hashable {
|
||||
// func hash(into hasher: inout Hasher) {
|
||||
// hasher.combine(kind)
|
||||
// }
|
||||
//
|
||||
// static func == (lhs: Import, rhs: Import) -> Bool {
|
||||
// lhs.kind == rhs.kind
|
||||
// }
|
||||
//}
|
|
@ -0,0 +1,5 @@
|
|||
import Foundation
|
||||
|
||||
protocol Inheritable {
|
||||
func isEqual(to other: Inheritable) -> Bool
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
struct Initializer: Token, HasAttributes, HasAccessibility {
|
||||
var parent: Reference<Token>?
|
||||
|
||||
var attributes: [Attribute]
|
||||
var accessibility: Accessibility
|
||||
var signature: Method.Signature
|
||||
var isRequired: Bool
|
||||
var isOptional: Bool
|
||||
}
|
||||
|
||||
extension Initializer: Inheritable {
|
||||
func isEqual(to other: Inheritable) -> Bool {
|
||||
guard let other = other as? Initializer else { return false }
|
||||
return signature.isApiEqual(to: other.signature)
|
||||
}
|
||||
}
|
||||
|
||||
extension Initializer: Serializable {
|
||||
func serialize() -> GeneratorContext {
|
||||
let accessibility: Accessibility
|
||||
if let parentProtocol = parent?.asProtocol {
|
||||
accessibility = parentProtocol.accessibility
|
||||
} else {
|
||||
accessibility = self.accessibility
|
||||
}
|
||||
return [
|
||||
"accessibility": accessibility.sourceName,
|
||||
"attributes": attributes,
|
||||
"signature": signature.description,
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
import Foundation
|
||||
|
||||
struct Method: Token, HasAttributes, HasAccessibility, HasName {
|
||||
var parent: Reference<Token>?
|
||||
|
||||
var attributes: [Attribute]
|
||||
var accessibility: Accessibility
|
||||
var name: String
|
||||
var signature: Signature
|
||||
var isOptional: Bool
|
||||
var isOverriding: Bool
|
||||
|
||||
var fullSignature: String {
|
||||
[
|
||||
accessibility.sourceName,
|
||||
"\(name)\(signature.description)",
|
||||
]
|
||||
.compactMap { $0.nilIfEmpty }
|
||||
.joined(separator: " ")
|
||||
}
|
||||
}
|
||||
|
||||
extension Method: Inheritable {
|
||||
func isEqual(to other: Inheritable) -> Bool {
|
||||
guard let other = other as? Method else { return false }
|
||||
return name == other.name && signature.isApiEqual(to: other.signature)
|
||||
}
|
||||
}
|
||||
|
||||
extension Method {
|
||||
var fullyQualifiedName: String {
|
||||
"\(name)\(signature.description.indented(times: 3).trimmed)"
|
||||
}
|
||||
|
||||
var isAsync: Bool {
|
||||
signature.asyncType.map { $0.isAsync || $0.isReasync } ?? false
|
||||
}
|
||||
|
||||
var isThrowing: Bool {
|
||||
signature.throwType.map { $0.isThrowing || $0.isRethrowing } ?? false
|
||||
}
|
||||
|
||||
var returnType: WrappableType? {
|
||||
signature.returnType
|
||||
}
|
||||
|
||||
var hasClosureParams: Bool {
|
||||
signature.parameters.contains { $0.isClosure }
|
||||
}
|
||||
|
||||
var hasOptionalParams: Bool {
|
||||
signature.parameters.contains { $0.isOptional }
|
||||
}
|
||||
|
||||
func serialize() -> [String : Any] {
|
||||
let call = signature.parameters
|
||||
.map { parameter in
|
||||
let value = "\(parameter.isInout ? "&" : "")\(parameter.usableName)\(parameter.isAutoClosure ? "()" : "")"
|
||||
if parameter.name == "_" {
|
||||
return value
|
||||
} else {
|
||||
return "\(parameter.name): \(value)"
|
||||
}
|
||||
}
|
||||
.joined(separator: ", ")
|
||||
|
||||
guard let parent else {
|
||||
fatalError("Failed to find parent of method \(fullSignature). Please file a bug.")
|
||||
}
|
||||
let stubFunctionPrefix = parent.isClass ? "Class" : "Protocol"
|
||||
let returnString = returnType == nil || returnType?.sugarized == "Void" ? "NoReturn" : ""
|
||||
let throwingString = isThrowing ? "Throwing" : ""
|
||||
let stubFunction = "Cuckoo.\(stubFunctionPrefix)Stub\(returnString)\(throwingString)Function"
|
||||
|
||||
let escapingParameterNames = signature.parameters.map { parameter in
|
||||
if parameter.isClosure && !parameter.isEscaping {
|
||||
let parameterCount = parameter.closureParamCount
|
||||
let parameterSignature = parameterCount > 0 ? (1...parameterCount).map { _ in "_" }.joined(separator: ", ") : "()"
|
||||
|
||||
// FIXME: Instead of parsing the closure return type here, Tokenizer should do it and pass the information in a data structure
|
||||
let returnSignature: String
|
||||
let closureReturnType = extractClosureReturnType(parameter: parameter.type.sugarized)
|
||||
if let closureReturnType = closureReturnType, !closureReturnType.isEmpty && closureReturnType != "Void" {
|
||||
returnSignature = " -> " + closureReturnType
|
||||
} else {
|
||||
returnSignature = ""
|
||||
}
|
||||
return "{ \(parameterSignature)\(returnSignature) in fatalError(\"This is a stub! It's not supposed to be called!\") }"
|
||||
} else {
|
||||
return parameter.usableName
|
||||
}
|
||||
}.joined(separator: ", ")
|
||||
|
||||
return [
|
||||
"self": self,
|
||||
"isOverriding": isOverriding,
|
||||
"name": name,
|
||||
"accessibility": accessibility.sourceName,
|
||||
"signature": signature.description,
|
||||
"parameters": signature.parameters,
|
||||
"parameterNames": signature.parameters.map { $0.usableName }.joined(separator: ", "),
|
||||
"escapingParameterNames": escapingParameterNames,
|
||||
"returnType": returnType?.explicitOptionalOnly.sugarized ?? "",
|
||||
"isAsync": isAsync,
|
||||
"isThrowing": isThrowing,
|
||||
"throwType": signature.throwType?.description ?? "",
|
||||
"fullyQualifiedName": fullyQualifiedName,
|
||||
"call": call,
|
||||
"parameterSignature": signature.parameters.map { $0.description }.joined(separator: ", "),
|
||||
"parameterSignatureWithoutNames": signature.parameters.map { "\($0.name): \($0.type)" }.joined(separator: ", "),
|
||||
"argumentSignature": signature.parameters.map { $0.type.description }.joined(separator: ", "),
|
||||
"stubFunction": stubFunction,
|
||||
"inputTypes": signature.parameters.map { $0.typeWithoutAttributes }.joined(separator: ", "),
|
||||
"isOptional": isOptional,
|
||||
"hasClosureParams": hasClosureParams,
|
||||
"hasOptionalParams": hasOptionalParams,
|
||||
"attributes": attributes,
|
||||
"genericParameters": signature.genericParameters.sourceDescription,
|
||||
"hasUnavailablePlatforms": hasUnavailablePlatforms,
|
||||
"unavailablePlatformsCheck": unavailablePlatformsCheck,
|
||||
]
|
||||
}
|
||||
|
||||
private func extractClosureReturnType(parameter: String) -> String? {
|
||||
var parenLevel = 0
|
||||
for i in 0..<parameter.count {
|
||||
let index = parameter.index(parameter.startIndex, offsetBy: i)
|
||||
let character = parameter[index]
|
||||
if character == "(" {
|
||||
parenLevel += 1
|
||||
} else if character == ")" {
|
||||
parenLevel -= 1
|
||||
if parenLevel == 0 {
|
||||
let returnSignature = String(parameter[parameter.index(after: index)..<parameter.endIndex])
|
||||
let regex = try! NSRegularExpression(pattern: "\\s*->\\s*(.*)\\s*")
|
||||
guard let result = regex.matches(in: returnSignature, range: NSRange(location: 0, length: returnSignature.count)).first else { return nil }
|
||||
return returnSignature[result.range(at: 1)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
struct MethodParameter: Token {
|
||||
var parent: Reference<Token>?
|
||||
|
||||
var name: String
|
||||
var innerName: String?
|
||||
var type: WrappableType
|
||||
var isInout: Bool
|
||||
|
||||
var nameAndInnerName: String {
|
||||
[name, innerName].compactMap { $0 }.joined(separator: " ")
|
||||
}
|
||||
|
||||
var usableName: String {
|
||||
innerName ?? name
|
||||
// if name == "_" {
|
||||
// guard let innerName else {
|
||||
// fatalError("Parameter inner name shouldn't be empty if name is an underscore. Please file a bug.")
|
||||
// }
|
||||
// return innerName
|
||||
// } else {
|
||||
// return name
|
||||
// }
|
||||
}
|
||||
|
||||
var description: String {
|
||||
"\(nameAndInnerName): \(isInout ? "inout " : "")\(type)"
|
||||
}
|
||||
|
||||
var typeWithoutAttributes: String {
|
||||
type.withoutAttributes.sugarized.trimmed
|
||||
}
|
||||
|
||||
var isClosure: Bool {
|
||||
typeWithoutAttributes.hasPrefix("(") && typeWithoutAttributes.range(of: "->") != nil
|
||||
}
|
||||
|
||||
var isAutoClosure: Bool {
|
||||
type.containsAttribute(named: "@autoclosure")
|
||||
}
|
||||
|
||||
var isOptional: Bool {
|
||||
type.isOptional
|
||||
}
|
||||
|
||||
var closureParamCount: Int {
|
||||
// make sure that the parameter is a closure and that it's not just an empty `() -> ...` closure
|
||||
guard isClosure && !"^\\s*\\(\\s*\\)".regexMatches(typeWithoutAttributes) else { return 0 }
|
||||
|
||||
var parenLevel = 0
|
||||
var parameterCount = 1
|
||||
for character in typeWithoutAttributes {
|
||||
switch character {
|
||||
case "(", "<":
|
||||
parenLevel += 1
|
||||
case ")", ">":
|
||||
parenLevel -= 1
|
||||
case ",":
|
||||
parameterCount += parenLevel == 1 ? 1 : 0
|
||||
default:
|
||||
break
|
||||
}
|
||||
if parenLevel == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return parameterCount
|
||||
}
|
||||
|
||||
var isEscaping: Bool {
|
||||
isClosure && (type.containsAttribute(named: "@escaping") || type.isOptional)
|
||||
}
|
||||
|
||||
func serialize() -> [String: Any] {
|
||||
return [
|
||||
"name": name,
|
||||
"innerName": innerName ?? "",
|
||||
"type": type,
|
||||
"nameAndInnerName": nameAndInnerName,
|
||||
"typeWithoutAttributes": typeWithoutAttributes,
|
||||
"isClosure": isClosure,
|
||||
"isOptional": isOptional,
|
||||
"isEscaping": isEscaping
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
import Foundation
|
||||
|
||||
extension Method {
|
||||
struct Signature {
|
||||
let genericParameters: [GenericParameter]
|
||||
let parameters: [MethodParameter]
|
||||
let asyncType: AsyncType?
|
||||
let throwType: ThrowType?
|
||||
let returnType: WrappableType?
|
||||
let whereConstraints: [String]
|
||||
|
||||
init(
|
||||
genericParameters: [GenericParameter],
|
||||
parameters: [MethodParameter],
|
||||
asyncType: AsyncType? = nil,
|
||||
throwType: ThrowType? = nil,
|
||||
returnType: WrappableType? = nil,
|
||||
whereConstraints: [String]
|
||||
) {
|
||||
self.genericParameters = genericParameters
|
||||
self.parameters = parameters.enumerated().map { index, parameter in
|
||||
MethodParameter(
|
||||
parent: parameter.parent,
|
||||
name: parameter.name,
|
||||
innerName: "p\(index)",
|
||||
type: parameter.type,
|
||||
isInout: parameter.isInout
|
||||
)
|
||||
}
|
||||
self.asyncType = asyncType
|
||||
self.throwType = throwType
|
||||
self.returnType = returnType
|
||||
self.whereConstraints = whereConstraints
|
||||
}
|
||||
|
||||
var description: String {
|
||||
let genericParametersString = genericParameters.map { $0.description }.joined(separator: ", ")
|
||||
let returnString: String?
|
||||
if let returnType {
|
||||
let trimmedReturnType = returnType.explicitOptionalOnly.sugarized.trimmed
|
||||
let returnsVoid = trimmedReturnType.isEmpty || trimmedReturnType == "Void"
|
||||
returnString = returnsVoid ? nil : "-> \(returnType)"
|
||||
} else {
|
||||
returnString = nil
|
||||
}
|
||||
let whereString = whereConstraints.isEmpty ? nil : "where \(whereConstraints.joined(separator: ", "))"
|
||||
return [
|
||||
genericParametersString.isEmpty ? nil : "<\(genericParametersString)>",
|
||||
"(\(parameters.map { $0.description }.joined(separator: ", ")))",
|
||||
asyncType?.description,
|
||||
throwType?.description,
|
||||
returnString,
|
||||
whereString,
|
||||
]
|
||||
.compactMap { $0 }
|
||||
.joined(separator: " ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Method.Signature {
|
||||
func isApiEqual(to other: Method.Signature) -> Bool {
|
||||
genericParameters == other.genericParameters
|
||||
&& parameters.elementsEqual(other.parameters) { $0.name == $1.name && $0.type == $1.type }
|
||||
&& asyncType == other.asyncType
|
||||
&& throwType == other.throwType
|
||||
&& returnType == other.returnType
|
||||
&& whereConstraints == other.whereConstraints
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import Foundation
|
||||
|
||||
/// This structure exists purely for supporting nested classes,
|
||||
/// it could be any container (like `struct` or `extension`).
|
||||
struct NamespaceDeclaration: Token, HasAccessibility, HasName, HasMembers {
|
||||
var parent: Reference<Token>?
|
||||
|
||||
var attributes: [Attribute]
|
||||
var accessibility: Accessibility
|
||||
var name: String
|
||||
var members: [Token]
|
||||
|
||||
func replacing(members: [Token]) -> NamespaceDeclaration {
|
||||
NamespaceDeclaration(
|
||||
parent: parent,
|
||||
attributes: attributes,
|
||||
accessibility: accessibility,
|
||||
name: name,
|
||||
members: members
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
struct ProtocolDeclaration: ContainerToken {
|
||||
var parent: Reference<Token>?
|
||||
|
||||
var attributes: [Attribute]
|
||||
var accessibility: Accessibility
|
||||
var name: String
|
||||
var genericParameters: [GenericParameter]
|
||||
var genericRequirements: [String]
|
||||
var inheritedTypes: [String]
|
||||
var members: [Token]
|
||||
var isNSObjectProtocol = false
|
||||
|
||||
func replacing(members: [Token]) -> ProtocolDeclaration {
|
||||
ProtocolDeclaration(
|
||||
parent: parent,
|
||||
attributes: attributes,
|
||||
accessibility: accessibility,
|
||||
name: name,
|
||||
genericParameters: genericParameters,
|
||||
genericRequirements: genericRequirements,
|
||||
inheritedTypes: inheritedTypes,
|
||||
members: members,
|
||||
isNSObjectProtocol: isNSObjectProtocol
|
||||
)
|
||||
}
|
||||
|
||||
func replacing(isNSObjectProtocol: Bool) -> ProtocolDeclaration {
|
||||
ProtocolDeclaration(
|
||||
parent: parent,
|
||||
attributes: attributes,
|
||||
accessibility: accessibility,
|
||||
name: name,
|
||||
genericParameters: genericParameters,
|
||||
genericRequirements: genericRequirements,
|
||||
inheritedTypes: inheritedTypes,
|
||||
members: members,
|
||||
isNSObjectProtocol: isNSObjectProtocol
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
protocol Serializable {
|
||||
func serialize() -> GeneratorContext
|
||||
}
|
||||
|
||||
typealias GeneratorContext = [String: Any]
|
||||
|
||||
extension GeneratorContext {
|
||||
mutating func merge(_ other: GeneratorContext) {
|
||||
merge(other, uniquingKeysWith: { $1 })
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element == GeneratorContext {
|
||||
func merge() -> GeneratorContext {
|
||||
var context: GeneratorContext = [:]
|
||||
forEach { context.merge($0) }
|
||||
return context
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
enum ThrowType: String, CustomStringConvertible, Equatable {
|
||||
case `throws`
|
||||
case `rethrows`
|
||||
|
||||
init?(string: String) {
|
||||
if string.trimmed.hasPrefix(ThrowType.throws.rawValue) {
|
||||
self = .throws
|
||||
} else if string.trimmed.hasPrefix(ThrowType.rethrows.rawValue) {
|
||||
self = .rethrows
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var isThrowing: Bool {
|
||||
self == .throws
|
||||
}
|
||||
|
||||
var isRethrowing: Bool {
|
||||
self == .rethrows
|
||||
}
|
||||
|
||||
var description: String {
|
||||
rawValue
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
protocol Token: Serializable {
|
||||
var parent: Reference<Token>? { get set }
|
||||
}
|
||||
|
||||
extension Token {
|
||||
func serialize() -> GeneratorContext {
|
||||
commonSerialize()
|
||||
}
|
||||
|
||||
func commonSerialize() -> GeneratorContext {
|
||||
[
|
||||
[
|
||||
"@type": "\(type(of: self))",
|
||||
"isImplementation": isClass,
|
||||
"hasParent": parent != nil,
|
||||
],
|
||||
(self as? ContainerToken)?.containerSerialize(),
|
||||
(self as? HasName)?.nameSerialize(),
|
||||
(parent?.value as? HasName).map { ["parentFullyQualifiedName": $0.fullyQualifiedName] },
|
||||
(self as? HasGenerics)?.genericsSerialize(),
|
||||
asProtocol.map { ["isNSObjectProtocol": $0.isNSObjectProtocol] },
|
||||
(self as? HasInheritance)?.inheritanceSerialize(),
|
||||
]
|
||||
.compactMap { $0 }
|
||||
.merge()
|
||||
}
|
||||
|
||||
var isMockable: Bool {
|
||||
[isClass, isProtocol, isVariable, isMethod].contains(true)
|
||||
}
|
||||
|
||||
var isVariable: Bool {
|
||||
self is Variable
|
||||
}
|
||||
|
||||
var isMethod: Bool {
|
||||
self is Method
|
||||
}
|
||||
|
||||
var isClass: Bool {
|
||||
self is ClassDeclaration
|
||||
}
|
||||
|
||||
var asClass: ClassDeclaration? {
|
||||
self as? ClassDeclaration
|
||||
}
|
||||
|
||||
var isProtocol: Bool {
|
||||
self is ProtocolDeclaration
|
||||
}
|
||||
|
||||
var asProtocol: ProtocolDeclaration? {
|
||||
self as? ProtocolDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
extension Token where Self: HasName {
|
||||
func nameSerialize() -> GeneratorContext {
|
||||
[
|
||||
"name": name,
|
||||
"mockName": mockName,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
extension Token where Self: HasGenerics {
|
||||
func genericsSerialize() -> GeneratorContext {
|
||||
let genericParametersString = genericParameters.map { $0.description }.joined(separator: ", ")
|
||||
let genericArgumentsString = genericParameters.map { $0.name }.joined(separator: ", ")
|
||||
let genericProtocolIdentity = isProtocol ? genericParameters.map { "\(Templates.staticGenericParameter).\($0.name) == \($0.name)" }.joined(separator: ", ") : nil
|
||||
let isGeneric = !genericParameters.isEmpty
|
||||
|
||||
return [
|
||||
"isGeneric": isGeneric,
|
||||
"genericParameters": isGeneric ? "<\(genericParametersString)>" : "",
|
||||
"genericArguments": isGeneric ? "<\(genericArgumentsString)>" : "",
|
||||
"genericProtocolIdentity": genericProtocolIdentity,
|
||||
]
|
||||
.compactMapValues { $0 }
|
||||
}
|
||||
}
|
||||
|
||||
extension Token where Self: HasInheritance {
|
||||
func inheritanceSerialize() -> GeneratorContext {
|
||||
[
|
||||
"inheritedTypes": inheritedTypes,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
extension Token where Self: HasAttributes {
|
||||
func attributesSerialize() -> GeneratorContext {
|
||||
[
|
||||
"attributes": attributes,
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
struct Variable: Token, HasAccessibility, HasAttributes {
|
||||
var parent: Reference<Token>?
|
||||
|
||||
var attributes: [Attribute]
|
||||
var accessibility: Accessibility
|
||||
var setterAccessibility: Accessibility?
|
||||
var name: String
|
||||
var type: WrappableType
|
||||
var isOverriding: Bool
|
||||
var isReadOnly: Bool {
|
||||
setterAccessibility?.isAccessible != true
|
||||
}
|
||||
|
||||
func serialize() -> [String: Any] {
|
||||
let readOnlyString = isReadOnly ? "ReadOnly" : ""
|
||||
let optionalString = type.isOptional && !isReadOnly ? "Optional" : ""
|
||||
|
||||
guard let parent else {
|
||||
fatalError("Failed to find parent of variable \(name). Please file a bug.")
|
||||
}
|
||||
|
||||
return [
|
||||
"isOverriding": isOverriding,
|
||||
"name": name,
|
||||
"type": type.sugarized,
|
||||
"nonOptionalType": type.unoptionaled.sugarized,
|
||||
"accessibility": accessibility.sourceName,
|
||||
"isReadOnly": isReadOnly,
|
||||
"stubType": (parent.isClass ? "Class" : "Protocol") + "ToBeStubbed\(readOnlyString)\(optionalString)Property",
|
||||
"verifyType": "Verify\(readOnlyString)\(optionalString)Property",
|
||||
"attributes": attributes,
|
||||
"hasUnavailablePlatforms": hasUnavailablePlatforms,
|
||||
"unavailablePlatformsCheck": unavailablePlatformsCheck,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
extension Variable: Inheritable {
|
||||
func isEqual(to other: Inheritable) -> Bool {
|
||||
guard let other = other as? Variable else { return false }
|
||||
return name == other.name
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
public enum WrappableType {
|
||||
enum WrappableType {
|
||||
indirect case optional(WrappableType)
|
||||
indirect case implicitlyUnwrappedOptional(WrappableType)
|
||||
indirect case attributed(WrappableType, attributes: [String])
|
||||
case type(String)
|
||||
|
||||
public var sugarized: String {
|
||||
var sugarized: String {
|
||||
switch self {
|
||||
case .optional(let wrapped):
|
||||
return "\(wrapped.sugarized)?"
|
||||
|
@ -17,7 +17,7 @@ public enum WrappableType {
|
|||
}
|
||||
}
|
||||
|
||||
public var desugarized: String {
|
||||
var desugarized: String {
|
||||
switch self {
|
||||
case .optional(let wrapped), .implicitlyUnwrappedOptional(let wrapped):
|
||||
return "Optional<\(wrapped.desugarized)>"
|
||||
|
@ -28,7 +28,7 @@ public enum WrappableType {
|
|||
}
|
||||
}
|
||||
|
||||
public var explicitOptionalOnly: WrappableType {
|
||||
var explicitOptionalOnly: WrappableType {
|
||||
switch self {
|
||||
case .optional(let wrapped), .implicitlyUnwrappedOptional(let wrapped):
|
||||
return .optional(wrapped.explicitOptionalOnly)
|
||||
|
@ -39,7 +39,7 @@ public enum WrappableType {
|
|||
}
|
||||
}
|
||||
|
||||
public var unoptionaled: WrappableType {
|
||||
var unoptionaled: WrappableType {
|
||||
switch self {
|
||||
case .optional(let wrapped), .implicitlyUnwrappedOptional(let wrapped):
|
||||
return wrapped.unoptionaled
|
||||
|
@ -50,7 +50,7 @@ public enum WrappableType {
|
|||
}
|
||||
}
|
||||
|
||||
public var unwrapped: WrappableType {
|
||||
var unwrapped: WrappableType {
|
||||
switch self {
|
||||
case .optional(let wrapped), .implicitlyUnwrappedOptional(let wrapped):
|
||||
return wrapped
|
||||
|
@ -61,7 +61,7 @@ public enum WrappableType {
|
|||
}
|
||||
}
|
||||
|
||||
public var withoutAttributes: WrappableType {
|
||||
var withoutAttributes: WrappableType {
|
||||
switch self {
|
||||
case .optional(let wrapped):
|
||||
return .optional(wrapped.withoutAttributes)
|
||||
|
@ -74,7 +74,7 @@ public enum WrappableType {
|
|||
}
|
||||
}
|
||||
|
||||
public var isOptional: Bool {
|
||||
var isOptional: Bool {
|
||||
switch self {
|
||||
case .optional, .implicitlyUnwrappedOptional:
|
||||
return true
|
||||
|
@ -85,7 +85,7 @@ public enum WrappableType {
|
|||
}
|
||||
}
|
||||
|
||||
public init(parsing value: String) {
|
||||
init(parsing value: String) {
|
||||
let trimmedValue = value.trimmed
|
||||
let optionalPrefix = "Optional<"
|
||||
if trimmedValue.hasPrefix("@") {
|
||||
|
@ -113,7 +113,7 @@ public enum WrappableType {
|
|||
}
|
||||
}
|
||||
|
||||
public func containsAttribute(named attribute: String) -> Bool {
|
||||
func containsAttribute(named attribute: String) -> Bool {
|
||||
switch self {
|
||||
case .optional(let wrapped), .implicitlyUnwrappedOptional(let wrapped):
|
||||
return wrapped.containsAttribute(named: attribute)
|
||||
|
@ -126,13 +126,13 @@ public enum WrappableType {
|
|||
}
|
||||
|
||||
extension WrappableType: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return sugarized
|
||||
var description: String {
|
||||
sugarized
|
||||
}
|
||||
}
|
||||
|
||||
extension WrappableType: Equatable {
|
||||
public static func ==(lhs: WrappableType, rhs: WrappableType) -> Bool {
|
||||
static func ==(lhs: WrappableType, rhs: WrappableType) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.optional(let lhsWrapped), .optional(let rhsWrapped)),
|
||||
(.implicitlyUnwrappedOptional(let lhsWrapped), .implicitlyUnwrappedOptional(let rhsWrapped)):
|
|
@ -2,6 +2,7 @@ import Foundation
|
|||
|
||||
struct TypeGuesser {
|
||||
static func guessType(from value: String) -> String? {
|
||||
guard !value.trimmed.isEmpty else { return nil }
|
||||
let value = value.trimmed
|
||||
let casting = checkCasting(from: value)
|
||||
guard casting == nil else { return casting }
|
|
@ -1,5 +1,4 @@
|
|||
import Foundation
|
||||
import SourceKittenFramework
|
||||
|
||||
extension String {
|
||||
var trimmed: String {
|
||||
|
@ -31,26 +30,19 @@ extension String {
|
|||
}
|
||||
}
|
||||
|
||||
extension Sequence {
|
||||
#if !swift(>=4.1)
|
||||
public func compactMap<O>(_ transform: (Element) -> O?) -> [O] {
|
||||
return self.flatMap(transform)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
func only<T>(_ type: T.Type) -> [T] {
|
||||
extension Sequence where Element: Token {
|
||||
func only<T: Token>(_ type: T.Type) -> [T] {
|
||||
return compactMap { $0 as? T }
|
||||
}
|
||||
|
||||
func noneOf<T>(_ type: T.Type) -> [Iterator.Element] {
|
||||
func noneOf<T: Token>(_ type: T.Type) -> [Iterator.Element] {
|
||||
return filter { !($0 is T) }
|
||||
}
|
||||
}
|
||||
|
||||
internal func extractRange(from dictionary: [String: SourceKitRepresentable], offset: Key, length: Key) -> CountableRange<Int>? {
|
||||
guard let offset = (dictionary[offset.rawValue] as? Int64).map(Int.init),
|
||||
let length = (dictionary[length.rawValue] as? Int64).map(Int.init) else { return nil }
|
||||
|
||||
return offset..<offset.advanced(by: length)
|
||||
}
|
||||
//func extractRange(from dictionary: [String: SourceKitRepresentable], offset: Key, length: Key) -> CountableRange<Int>? {
|
||||
// guard let offset = (dictionary[offset.rawValue] as? Int64).map(Int.init),
|
||||
// let length = (dictionary[length.rawValue] as? Int64).map(Int.init) else { return nil }
|
||||
//
|
||||
// return offset..<offset.advanced(by: length)
|
||||
//}
|
|
@ -0,0 +1,77 @@
|
|||
import XCTest
|
||||
|
||||
final class OrderedSetTest: XCTestCase {
|
||||
func testInitializers() {
|
||||
_ = OrderedSet<Int>()
|
||||
_ = [] as OrderedSet<String>
|
||||
_ = ["1", "2", "4"] as OrderedSet<String>
|
||||
}
|
||||
|
||||
func testEmpty() {
|
||||
let set = OrderedSet<Double>()
|
||||
XCTAssertEqual(set.values, [])
|
||||
}
|
||||
|
||||
func testBasicUsage() {
|
||||
var set = OrderedSet<Int>()
|
||||
set.insert(2)
|
||||
XCTAssertEqual(set.values, [2])
|
||||
set.insert(0)
|
||||
XCTAssertEqual(set.values, [2, 0])
|
||||
set.insert(1)
|
||||
XCTAssertEqual(set.values, [2, 0, 1])
|
||||
}
|
||||
|
||||
func testDeduplicationInit() {
|
||||
let set: OrderedSet<Int> = [1, 2, 3, 2, 0, 1]
|
||||
XCTAssertEqual(set.values, [1, 2, 3, 0])
|
||||
}
|
||||
|
||||
func testDeduplicationInsert() {
|
||||
var set = OrderedSet<String>()
|
||||
set.insert("1")
|
||||
XCTAssertEqual(set.values, ["1"])
|
||||
set.insert("11")
|
||||
XCTAssertEqual(set.values, ["1", "11"])
|
||||
set.insert("111")
|
||||
XCTAssertEqual(set.values, ["1", "11", "111"])
|
||||
set.insert("11")
|
||||
XCTAssertEqual(set.values, ["1", "11", "111"])
|
||||
set.insert("1")
|
||||
XCTAssertEqual(set.values, ["1", "11", "111"])
|
||||
}
|
||||
|
||||
func testRemove() {
|
||||
var set: OrderedSet<String> = ["gg", "bg", "wp", "ez"]
|
||||
set.remove("ez")
|
||||
XCTAssertEqual(set.values, ["gg", "bg", "wp"])
|
||||
set.remove("bg")
|
||||
XCTAssertEqual(set.values, ["gg", "wp"])
|
||||
}
|
||||
|
||||
func testContains() {
|
||||
var set: OrderedSet<Int> = [1, 2, 3, 4, 5]
|
||||
XCTAssertFalse(set.contains(6))
|
||||
XCTAssertTrue(set.contains(1))
|
||||
set.insert(6)
|
||||
XCTAssertTrue(set.contains(6))
|
||||
set.remove(2)
|
||||
XCTAssertFalse(set.contains(2))
|
||||
}
|
||||
|
||||
func testIntersection() {
|
||||
let set1: OrderedSet<Int> = [1, 2, 3, 4]
|
||||
let set2: OrderedSet<Int> = [2, 3, 4, 5]
|
||||
XCTAssertEqual(set1.intersection(set2).values, [2, 3, 4])
|
||||
XCTAssertEqual(set1.values, [1, 2, 3, 4])
|
||||
XCTAssertEqual(set2.values, [2, 3, 4, 5])
|
||||
}
|
||||
|
||||
func testUnion() {
|
||||
let set1: OrderedSet<Int> = [1, 2, 3, 4]
|
||||
let set2: OrderedSet<Int> = [2, 3, 4, 5]
|
||||
XCTAssertEqual(set1.union(set2).values, [1, 2, 3, 4, 5])
|
||||
XCTAssertEqual(set1.values, [1, 2, 3, 4])
|
||||
XCTAssertEqual(set2.values, [2, 3, 4, 5])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:feb332ba0a027812b1ee7f552321d6069a46207e5cd0f64fa9bb78e2a261b366
|
||||
size 36606619
|
3
Makefile
3
Makefile
|
@ -2,6 +2,9 @@
|
|||
|
||||
dev:
|
||||
(killall Xcode || true)
|
||||
# Unzip SwiftSyntax XCFramework.
|
||||
pushd Generator; unzip -o lib_InternalSwiftSyntaxParser.xcframework.zip; popd
|
||||
# Generate Xcode structure.
|
||||
tuist generate --no-open
|
||||
# Use Bundler if available, otherwise just call system-wide CocoaPods.
|
||||
if ! command -v bundle &> /dev/null; then bundle install && bundle exec pod install; else pod install; fi
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
//
|
||||
// Cuckoo-BridgingHeader.h
|
||||
// Cuckoo
|
||||
//
|
||||
// Created by Matyáš Kříž on 28/05/2019.
|
||||
//
|
||||
|
||||
#ifndef Cuckoo_BridgingHeader_h
|
||||
#define Cuckoo_BridgingHeader_h
|
||||
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
//
|
||||
// NSValueConvertible.swift
|
||||
// Cuckoo+OCMock-iOS
|
||||
//
|
||||
// Created by Matyáš Kříž on 28/05/2019.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreGraphics
|
||||
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
//
|
||||
// NSInvocation+OCMockWrapper.h
|
||||
// Cuckoo-CocoaPodsTests
|
||||
//
|
||||
// Created by Matyáš Kříž on 27/05/2019.
|
||||
// Copyright © 2019 Cuckoo. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
//
|
||||
// NSInvocation+OCMockWrapper.m
|
||||
// Cuckoo-CocoaPodsTests
|
||||
//
|
||||
// Created by Matyáš Kříž on 27/05/2019.
|
||||
// Copyright © 2019 Cuckoo. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSInvocation+OCMockWrapper.h"
|
||||
#import <OCMock/OCMFunctions.h>
|
||||
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
//
|
||||
// NSObject+TrustMe.h
|
||||
// Cuckoo-CocoaPodsTests
|
||||
//
|
||||
// Created by Tadeáš Kříž on 28/05/2019.
|
||||
// Copyright © 2019 Cuckoo. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
//
|
||||
// NSObject+TrustMe.m
|
||||
// Cuckoo-CocoaPodsTests
|
||||
//
|
||||
// Created by Tadeáš Kříž on 28/05/2019.
|
||||
// Copyright © 2019 Cuckoo. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSObject+TrustMe.h"
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
//
|
||||
// OCMockObject+CuckooMockObject.h
|
||||
// Cuckoo+OCMock-iOS
|
||||
//
|
||||
// Created by Matyáš Kříž on 28/05/2019.
|
||||
//
|
||||
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
//
|
||||
// OCMockObject+CuckooMockObject.m
|
||||
// Cuckoo+OCMock-iOS
|
||||
//
|
||||
// Created by Matyáš Kříž on 28/05/2019.
|
||||
//
|
||||
|
||||
#import "OCMockObject+CuckooMockObject.h"
|
||||
|
||||
@implementation CuckooMockObject
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue