Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
OrkhanAlikhanov committed May 29, 2021
0 parents commit e19c117
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.DS_Store
/.build
/.swiftpm
/Packages
/*.xcodeproj
xcuserdata/
15 changes: 15 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// swift-tools-version:5.3

import PackageDescription

let package = Package(
name: "ChainSwift",
products: [
.library(name: "ChainSwift", targets: ["ChainSwift"]),
],

targets: [
.target(name: "ChainSwift", dependencies: []),
.testTarget(name: "ChainSwiftTests", dependencies: ["ChainSwift"]),
]
)
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ChainSwift

A description of this package.
52 changes: 52 additions & 0 deletions Sources/ChainSwift/ChainSwift.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// Chain.swift
// ChainSwift
//
// Created by Orkhan Alikhanov on 5/29/21.
//

@dynamicMemberLookup
public struct Chain<Base> {
public var ch: Base

init(_ base: Base) {
self.ch = base
}

public subscript<T>(dynamicMember keyPath: WritableKeyPath<Base, T>) -> Callable<Base, T> {
Callable(ch, keyPath: keyPath)
}
}

public class Callable<Base, T> {
var base: Base
var keyPath: WritableKeyPath<Base, T>

init(_ base: Base, keyPath: WritableKeyPath<Base, T>) {
self.base = base
self.keyPath = keyPath
}

@discardableResult
public func callAsFunction(_ value: T) -> Chain<Base> {
base[keyPath: keyPath] = value
return Chain(base)
}
}

public protocol Chainable {
associatedtype ChainableBase

static var ch: Chain<ChainableBase>.Type { get }
var ch: Chain<ChainableBase> { get }
}

public extension Chainable {
static var ch: Chain<Self>.Type {
Chain<Self>.self
}

var ch: Chain<Self> {
Chain(self)
}
}
86 changes: 86 additions & 0 deletions Tests/ChainSwiftTests/ChainSwiftTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import XCTest
import ChainSwift

enum MyEnum {
case value1
case value2
}

class MyClass {
var text = ""
var int = 0
var myEnum: MyEnum = .value1
}

struct MyStruct {
var text = ""
var int = 0
var myEnum: MyEnum = .value1
}

extension MyClass: Chainable { }
extension MyStruct: Chainable { }


/// Ensure compiles with NSObject
import Foundation
extension NSObject: Chainable { }

final class ChainSwiftTests: XCTestCase {
func testClassWorks() {
let myClass = MyClass()

XCTAssertEqual(myClass.text, "")
XCTAssertEqual(myClass.int, 0)
XCTAssertEqual(myClass.myEnum, .value1)

myClass.ch
.text("It works")
.int(99)
.myEnum(.value2)

XCTAssertEqual(myClass.text, "It works")
XCTAssertEqual(myClass.int, 99)
XCTAssertEqual(myClass.myEnum, .value2)
}

func testTakingChValueWorks() {
let myClass = MyClass().ch
.text("It works")
.int(99)
.myEnum(.value2)
.ch

XCTAssertEqual(myClass.text, "It works")
XCTAssertEqual(myClass.int, 99)
XCTAssertEqual(myClass.myEnum, .value2)
}

func testStructWorks() {
let myStruct = MyStruct()

XCTAssertEqual(myStruct.text, "")
XCTAssertEqual(myStruct.int, 0)
XCTAssertEqual(myStruct.myEnum, .value1)

let updatedMyStruct = myStruct.ch
.text("It works")
.int(99)
.myEnum(.value2)
.ch

XCTAssertEqual(myStruct.text, "")
XCTAssertEqual(myStruct.int, 0)
XCTAssertEqual(myStruct.myEnum, .value1)

XCTAssertEqual(updatedMyStruct.text, "It works")
XCTAssertEqual(updatedMyStruct.int, 99)
XCTAssertEqual(updatedMyStruct.myEnum, .value2)
}

static var allTests = [
("testClassWorks", testClassWorks),
("testTakingChValueWorks", testTakingChValueWorks),
("testStructWorks", testStructWorks),
]
}
9 changes: 9 additions & 0 deletions Tests/ChainSwiftTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import XCTest

#if !canImport(ObjectiveC)
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(ChainSwiftTests.allTests),
]
}
#endif
7 changes: 7 additions & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import XCTest

import ChainSwiftTests

var tests = [XCTestCaseEntry]()
tests += ChainSwiftTests.allTests()
XCTMain(tests)

0 comments on commit e19c117

Please sign in to comment.