├── README ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png └── 6.png ├── smck ├── Parser │ ├── JSParser.swift │ ├── CSSAST.swift │ ├── H5AST.swift │ ├── analyzeExtension.swift │ ├── ParsingSecondRoundOneFile.swift │ ├── ParsingImplementation.swift │ ├── CSSSb.swift │ ├── ParsingProtocol.swift │ ├── H5Sb.swift │ ├── ParsingObject.swift │ ├── ParsingMacro.swift │ ├── JSSb.swift │ ├── ParsingProperty.swift │ ├── ParsingImport.swift │ ├── JSLexer.swift │ ├── SMLangAST.swift │ ├── CSSLexer.swift │ ├── ParsingInterface.swift │ ├── CSSParser.swift │ └── ParsingMethod.swift ├── Plugin │ ├── H5ToNativePlugin.swift │ └── UnUseObjectPlugin.swift ├── Lib │ └── RxSwift │ │ ├── RecursiveLock.swift │ │ ├── ScheduledItemType.swift │ │ ├── Disposable.swift │ │ ├── Disposables.swift │ │ ├── Cancelable.swift │ │ ├── InvocableType.swift │ │ ├── SynchronizedUnsubscribeType.swift │ │ ├── Never.swift │ │ ├── Empty.swift │ │ ├── AnonymousInvocable.swift │ │ ├── LockOwnerType.swift │ │ ├── DisposeBase.swift │ │ ├── SynchronizedDisposeType.swift │ │ ├── SynchronizedOnType.swift │ │ ├── Error.swift │ │ ├── InvocableScheduledItem.swift │ │ ├── SubscriptionDisposable.swift │ │ ├── ObservableConvertibleType.swift │ │ ├── DispatchQueue+Extensions.swift │ │ ├── SynchronizedSubscribeType.swift │ │ ├── String+Rx.swift │ │ ├── InfiniteSequence.swift │ │ ├── RxMutableBox.swift │ │ ├── SubjectType.swift │ │ ├── NopDisposable.swift │ │ ├── HistoricalScheduler.swift │ │ ├── StartWith.swift │ │ ├── ConnectableObservableType.swift │ │ ├── ScheduledItem.swift │ │ ├── AnonymousObserver.swift │ │ ├── ObserverBase.swift │ │ ├── Lock.swift │ │ ├── Observable+Debug.swift │ │ ├── BooleanDisposable.swift │ │ ├── Observable.swift │ │ ├── ObserverType.swift │ │ ├── ImmediateScheduler.swift │ │ ├── GroupedObservable.swift │ │ ├── Repeat.swift │ │ ├── Bag+Rx.swift │ │ ├── AddRef.swift │ │ ├── ToArray.swift │ │ ├── ImmediateSchedulerType.swift │ │ ├── DelaySubscription.swift │ │ ├── DefaultIfEmpty.swift │ │ ├── Errors.swift │ │ ├── ScheduledDisposable.swift │ │ ├── BinaryDisposable.swift │ │ ├── Sequence.swift │ │ ├── ObservableType.swift │ │ ├── Deferred.swift │ │ ├── Range.swift │ │ ├── Filter.swift │ │ ├── TakeLast.swift │ │ ├── OperationQueueScheduler.swift │ │ ├── Just.swift │ │ ├── Rx.swift │ │ ├── Concat.swift │ │ ├── Reactive.swift │ │ ├── Do.swift │ │ ├── Sink.swift │ │ ├── SubscribeOn.swift │ │ ├── AnonymousDisposable.swift │ │ ├── Scan.swift │ │ ├── AnonymousObservable.swift │ │ ├── Variable.swift │ │ ├── Observable+Concurrency.swift │ │ ├── Event.swift │ │ ├── Optional.swift │ │ ├── ElementAt.swift │ │ ├── Platform.Darwin.swift │ │ ├── AnyObserver.swift │ │ ├── DistinctUntilChanged.swift │ │ ├── SerialDisposable.swift │ │ ├── SchedulerServices+Emulation.swift │ │ ├── SingleAsync.swift │ │ ├── Timer.swift │ │ ├── Multicast.swift │ │ ├── Generate.swift │ │ ├── Using.swift │ │ ├── MainScheduler.swift │ │ ├── Reduce.swift │ │ ├── SingleAssignmentDisposable.swift │ │ ├── DisposeBag.swift │ │ ├── HistoricalSchedulerTimeConverter.swift │ │ ├── Observable+Aggregate.swift │ │ ├── ObserveOnSerialDispatchQueue.swift │ │ ├── AsyncLock.swift │ │ ├── SwitchIfEmpty.swift │ │ ├── RefCount.swift │ │ ├── SchedulerType.swift │ │ ├── Debug.swift │ │ ├── Debounce.swift │ │ ├── Platform.Linux.swift │ │ ├── ShareReplay1.swift │ │ ├── VirtualTimeConverterType.swift │ │ ├── Producer.swift │ │ ├── ConcurrentMainScheduler.swift │ │ └── TakeUntil.swift ├── main.swift ├── Global │ ├── SeekFolderFiles.swift │ └── Sb.swift └── Console │ └── Console.swift ├── smck.xcodeproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── .gitignore └── README.md /README/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/smck/master/README/1.png -------------------------------------------------------------------------------- /README/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/smck/master/README/2.png -------------------------------------------------------------------------------- /README/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/smck/master/README/3.png -------------------------------------------------------------------------------- /README/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/smck/master/README/4.png -------------------------------------------------------------------------------- /README/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/smck/master/README/5.png -------------------------------------------------------------------------------- /README/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ming1016/smck/master/README/6.png -------------------------------------------------------------------------------- /smck/Parser/JSParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JSParser.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/5/2. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /smck.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /smck/Plugin/H5ToNativePlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // H5ToNativePlugin.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/7/24. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/RecursiveLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RecursiveLock.swift 3 | // Platform 4 | // 5 | // Created by Krunoslav Zaher on 12/18/16. 6 | // Copyright © 2016 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | typealias RecursiveLock = NSRecursiveLock 12 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ScheduledItemType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScheduledItemType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 11/7/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | protocol ScheduledItemType 10 | : Cancelable 11 | , InvocableType { 12 | func invoke() 13 | } 14 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Disposable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Disposable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/8/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Respresents a disposable resource. 10 | public protocol Disposable { 11 | /// Dispose resource. 12 | func dispose() 13 | } 14 | -------------------------------------------------------------------------------- /smck/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // smck 4 | // 5 | // Created by daiming on 2017/3/11. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let checker = Checker() 12 | if CommandLine.argc < 2 { 13 | checker.interactiveModel() 14 | } else { 15 | checker.staticMode() 16 | } 17 | 18 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Disposables.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Disposables.swift 3 | // RxSwift 4 | // 5 | // Created by Mohsen Ramezanpoor on 01/08/2016. 6 | // Copyright © 2016 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// A collection of utility methods for common disposable operations. 10 | public struct Disposables { 11 | private init() {} 12 | } 13 | 14 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Cancelable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Cancelable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/12/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents disposable resource with state tracking. 10 | public protocol Cancelable : Disposable { 11 | /// Was resource disposed. 12 | var isDisposed: Bool { get } 13 | } 14 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/InvocableType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InvocableType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 11/7/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | protocol InvocableType { 10 | func invoke() 11 | } 12 | 13 | protocol InvocableWithValueType { 14 | associatedtype Value 15 | 16 | func invoke(_ value: Value) 17 | } 18 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SynchronizedUnsubscribeType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SynchronizedUnsubscribeType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/25/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | protocol SynchronizedUnsubscribeType : class { 10 | associatedtype DisposeKey 11 | 12 | func synchronizedUnsubscribe(_ disposeKey: DisposeKey) 13 | } 14 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Never.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Never.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 8/30/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class Never : Producer { 10 | override func subscribe(_ observer: O) -> Disposable where O.E == Element { 11 | return Disposables.create() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Empty.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Empty.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 8/30/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class Empty : Producer { 10 | override func subscribe(_ observer: O) -> Disposable where O.E == Element { 11 | observer.on(.completed) 12 | return Disposables.create() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/AnonymousInvocable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnonymousInvocable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 11/7/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | struct AnonymousInvocable : InvocableType { 10 | private let _action: () -> () 11 | 12 | init(_ action: @escaping () -> ()) { 13 | _action = action 14 | } 15 | 16 | func invoke() { 17 | _action() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/LockOwnerType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LockOwnerType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/25/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | protocol LockOwnerType : class, Lock { 10 | var _lock: RecursiveLock { get } 11 | } 12 | 13 | extension LockOwnerType { 14 | func lock() { 15 | _lock.lock() 16 | } 17 | 18 | func unlock() { 19 | _lock.unlock() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/DisposeBase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DisposeBase.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 4/4/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Base class for all disposables. 10 | public class DisposeBase { 11 | init() { 12 | #if TRACE_RESOURCES 13 | let _ = Resources.incrementTotal() 14 | #endif 15 | } 16 | 17 | deinit { 18 | #if TRACE_RESOURCES 19 | let _ = Resources.decrementTotal() 20 | #endif 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SynchronizedDisposeType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SynchronizedDisposeType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/25/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | protocol SynchronizedDisposeType : class, Disposable, Lock { 10 | func _synchronized_dispose() 11 | } 12 | 13 | extension SynchronizedDisposeType { 14 | func synchronizedDispose() { 15 | lock(); defer { unlock() } 16 | _synchronized_dispose() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SynchronizedOnType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SynchronizedOnType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/25/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | protocol SynchronizedOnType : class, ObserverType, Lock { 10 | func _synchronized_on(_ event: Event) 11 | } 12 | 13 | extension SynchronizedOnType { 14 | func synchronizedOn(_ event: Event) { 15 | lock(); defer { unlock() } 16 | _synchronized_on(event) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /smck/Parser/CSSAST.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CSSAST.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/4/19. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct CSSSelector { 12 | var selectorName:String 13 | var propertys:[String:String] 14 | } 15 | 16 | class CSSFile { 17 | private(set) var selectors = [String:CSSSelector]() 18 | 19 | func addSelector(_ selector:CSSSelector) { 20 | selectors["\(selector.selectorName)"] = selector 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smck/Parser/H5AST.swift: -------------------------------------------------------------------------------- 1 | // 2 | // H5AST.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/4/17. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct H5Tag { 12 | let name: String 13 | let subs: [H5Tag] 14 | let attributes: [String:String] 15 | let value: String 16 | } 17 | 18 | class H5File { 19 | private(set) var tags = [H5Tag]() 20 | var cssFile = CSSFile() 21 | 22 | func addTag(_ tag:H5Tag) { 23 | tags.append(tag) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /smck/Parser/analyzeExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // analyzeExtension.swift 3 | // smck 4 | // 5 | // Created by didi on 2017/4/15. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Character { 12 | var value: Int32 { 13 | return Int32(String(self).unicodeScalars.first!.value) 14 | } 15 | var isSpace: Bool { 16 | return isspace(value) != 0 17 | } 18 | var isAlphanumeric: Bool { 19 | return isalnum(value) != 0 || self == "_" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smck/Parser/ParsingSecondRoundOneFile.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParsingSecondRoundOneFile.swift 3 | // SMCheckProjectCL 4 | // 5 | // Created by didi on 2017/3/9. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ParsingSecondRoundOneFile { 12 | class func parsing(aFile:File, allFiles:[String:File]) -> Observable { 13 | return Observable.create({ (observer) -> Disposable in 14 | 15 | 16 | return Disposables.create {} 17 | }) 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Error.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Error.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 8/30/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class Error : Producer { 10 | private let _error: Swift.Error 11 | 12 | init(error: Swift.Error) { 13 | _error = error 14 | } 15 | 16 | override func subscribe(_ observer: O) -> Disposable where O.E == Element { 17 | observer.on(.error(_error)) 18 | return Disposables.create() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/InvocableScheduledItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InvocableScheduledItem.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 11/7/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | struct InvocableScheduledItem : InvocableType { 10 | 11 | let _invocable: I 12 | let _state: I.Value 13 | 14 | init(invocable: I, state: I.Value) { 15 | _invocable = invocable 16 | _state = state 17 | } 18 | 19 | func invoke() { 20 | _invocable.invoke(_state) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smck/Parser/ParsingImplementation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParsingImplementation.swift 3 | // SMCheckProject 4 | // 5 | // Created by daiming on 2017/2/28. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ParsingImplementation { 12 | class func parsing(line:String, inObject:Object) { 13 | // let aline = line.replacingOccurrences(of: Sb.atImplementation, with: "") 14 | // let tokens = ParsingBase.createOCLines(content: aline); 15 | // for tk in tokens { 16 | // 17 | // } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SubscriptionDisposable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubscriptionDisposable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/25/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | struct SubscriptionDisposable : Disposable { 10 | private let _key: T.DisposeKey 11 | private weak var _owner: T? 12 | 13 | init(owner: T, key: T.DisposeKey) { 14 | _owner = owner 15 | _key = key 16 | } 17 | 18 | func dispose() { 19 | _owner?.synchronizedUnsubscribe(_key) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ObservableConvertibleType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObservableConvertibleType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 9/17/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Type that can be converted to observable sequence (`Observer`). 10 | public protocol ObservableConvertibleType { 11 | /// Type of elements in sequence. 12 | associatedtype E 13 | 14 | /// Converts `self` to `Observable` sequence. 15 | /// 16 | /// - returns: Observable sequence that represents `self`. 17 | func asObservable() -> Observable 18 | } 19 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/DispatchQueue+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DispatchQueue+Extensions.swift 3 | // Platform 4 | // 5 | // Created by Krunoslav Zaher on 10/22/16. 6 | // Copyright © 2016 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | import Dispatch 10 | 11 | extension DispatchQueue { 12 | private static var token: DispatchSpecificKey<()> = { 13 | let key = DispatchSpecificKey<()>() 14 | DispatchQueue.main.setSpecific(key: key, value: ()) 15 | return key 16 | }() 17 | 18 | static var isMain: Bool { 19 | return DispatchQueue.getSpecific(key: token) != nil 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smck/Parser/CSSSb.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CSSSb.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/4/18. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class CSSSb { 12 | // 13 | public static let braceL = "{" 14 | public static let braceR = "}" 15 | public static let pSign = "#" 16 | public static let dot = "." 17 | public static let semicolon = ";" 18 | public static let colon = ":" 19 | public static let rBktL = "(" 20 | public static let rBktR = ")" 21 | 22 | public static let empty = "" 23 | public static let space = " " 24 | } 25 | 26 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SynchronizedSubscribeType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SynchronizedSubscribeType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/25/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | protocol SynchronizedSubscribeType : class, ObservableType, Lock { 10 | func _synchronized_subscribe(_ observer: O) -> Disposable where O.E == E 11 | } 12 | 13 | extension SynchronizedSubscribeType { 14 | func synchronizedSubscribe(_ observer: O) -> Disposable where O.E == E { 15 | lock(); defer { unlock() } 16 | return _synchronized_subscribe(observer) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/String+Rx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Rx.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 12/25/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | extension String { 10 | /// This is needed because on Linux Swift doesn't have `rangeOfString(..., options: .BackwardsSearch)` 11 | func lastIndexOf(_ character: Character) -> Index? { 12 | var index = endIndex 13 | while index > startIndex { 14 | index = self.index(before: index) 15 | if self[index] == character { 16 | return index 17 | } 18 | } 19 | 20 | return nil 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smck/Parser/ParsingProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParsingProtocol.swift 3 | // SMCheckProject 4 | // 5 | // Created by didi on 2017/2/28. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ParsingProtocol { 12 | //获取Protocol的name 13 | class func parsingNameFrom(line:String) -> String { 14 | guard let name = self.tokensFrom(line: line).first else { 15 | return "" 16 | } 17 | return name 18 | } 19 | 20 | class func tokensFrom(line:String) -> [String] { 21 | let aLine = line.replacingOccurrences(of: Sb.atProtocol, with: "") 22 | return ParsingBase.createOCTokens(conent: aLine) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/InfiniteSequence.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InfiniteSequence.swift 3 | // Platform 4 | // 5 | // Created by Krunoslav Zaher on 6/13/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Sequence that repeats `repeatedValue` infinite number of times. 10 | struct InfiniteSequence : Sequence { 11 | typealias Element = E 12 | typealias Iterator = AnyIterator 13 | 14 | private let _repeatedValue: E 15 | 16 | init(repeatedValue: E) { 17 | _repeatedValue = repeatedValue 18 | } 19 | 20 | func makeIterator() -> Iterator { 21 | let repeatedValue = _repeatedValue 22 | return AnyIterator { 23 | return repeatedValue 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/RxMutableBox.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RxMutableBox.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 5/22/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Creates mutable reference wrapper for any type. 10 | final class RxMutableBox : CustomDebugStringConvertible { 11 | /// Wrapped value 12 | var value : T 13 | 14 | /// Creates reference wrapper for `value`. 15 | /// 16 | /// - parameter value: Value to wrap. 17 | init (_ value: T) { 18 | self.value = value 19 | } 20 | } 21 | 22 | extension RxMutableBox { 23 | /// - returns: Box description. 24 | var debugDescription: String { 25 | return "MutatingBox(\(self.value))" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SubjectType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubjectType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/1/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents an object that is both an observable sequence as well as an observer. 10 | public protocol SubjectType : ObservableType { 11 | /// The type of the observer that represents this subject. 12 | /// 13 | /// Usually this type is type of subject itself, but it doesn't have to be. 14 | associatedtype SubjectObserverType : ObserverType 15 | 16 | /// Returns observer interface for subject. 17 | /// 18 | /// - returns: Observer interface for subject. 19 | func asObserver() -> SubjectObserverType 20 | 21 | } 22 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/NopDisposable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NopDisposable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/15/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents a disposable that does nothing on disposal. 10 | /// 11 | /// Nop = No Operation 12 | fileprivate struct NopDisposable : Disposable { 13 | 14 | fileprivate static let noOp: Disposable = NopDisposable() 15 | 16 | fileprivate init() { 17 | 18 | } 19 | 20 | /// Does nothing. 21 | public func dispose() { 22 | } 23 | } 24 | 25 | extension Disposables { 26 | /** 27 | Creates a disposable that does nothing on disposal. 28 | */ 29 | static public func create() -> Disposable { 30 | return NopDisposable.noOp 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /smck/Parser/H5Sb.swift: -------------------------------------------------------------------------------- 1 | // 2 | // H5Sb.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/4/18. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class H5Sb { 12 | 13 | public static let divide = "/" 14 | public static let agBktL = "<" 15 | public static let agBktR = ">" 16 | public static let quotM = "\"" 17 | public static let sQuot = "'" 18 | public static let equal = "=" 19 | //css 20 | 21 | //js 22 | public static let add = "+" 23 | public static let minus = "-" 24 | public static let asterisk = "*" 25 | public static let comma = "," 26 | 27 | // public static let 28 | 29 | public static let empty = "" 30 | public static let space = " " 31 | public static let newLine = "\n" 32 | } 33 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/HistoricalScheduler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HistoricalScheduler.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 12/27/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | import struct Foundation.Date 10 | 11 | /// Provides a virtual time scheduler that uses `Date` for absolute time and `NSTimeInterval` for relative time. 12 | public class HistoricalScheduler : VirtualTimeScheduler { 13 | 14 | /** 15 | Creates a new historical scheduler with initial clock value. 16 | 17 | - parameter initialClock: Initial value for virtual clock. 18 | */ 19 | public init(initialClock: RxTime = Date(timeIntervalSince1970: 0)) { 20 | super.init(initialClock: initialClock, converter: HistoricalSchedulerTimeConverter()) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/StartWith.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StartWith.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 4/6/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class StartWith: Producer { 10 | let elements: [Element] 11 | let source: Observable 12 | 13 | init(source: Observable, elements: [Element]) { 14 | self.source = source 15 | self.elements = elements 16 | super.init() 17 | } 18 | 19 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 20 | for e in elements { 21 | observer.on(.next(e)) 22 | } 23 | 24 | return (sink: Disposables.create(), subscription: source.subscribe(observer)) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ConnectableObservableType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ConnectableObservableType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/1/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /** 10 | Represents an observable sequence wrapper that can be connected and disconnected from its underlying observable sequence. 11 | */ 12 | public protocol ConnectableObservableType : ObservableType { 13 | /** 14 | Connects the observable wrapper to its source. All subscribed observers will receive values from the underlying observable sequence as long as the connection is established. 15 | 16 | - returns: Disposable used to disconnect the observable wrapper from its source, causing subscribed observer to stop receiving values from the underlying observable sequence. 17 | */ 18 | func connect() -> Disposable 19 | } 20 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ScheduledItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScheduledItem.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 9/2/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | struct ScheduledItem 10 | : ScheduledItemType 11 | , InvocableType { 12 | typealias Action = (T) -> Disposable 13 | 14 | private let _action: Action 15 | private let _state: T 16 | 17 | private let _disposable = SingleAssignmentDisposable() 18 | 19 | var isDisposed: Bool { 20 | return _disposable.isDisposed 21 | } 22 | 23 | init(action: @escaping Action, state: T) { 24 | _action = action 25 | _state = state 26 | } 27 | 28 | func invoke() { 29 | _disposable.setDisposable(_action(_state)) 30 | } 31 | 32 | func dispose() { 33 | _disposable.dispose() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/AnonymousObserver.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnonymousObserver.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/8/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class AnonymousObserver : ObserverBase { 10 | typealias Element = ElementType 11 | 12 | typealias EventHandler = (Event) -> Void 13 | 14 | private let _eventHandler : EventHandler 15 | 16 | init(_ eventHandler: @escaping EventHandler) { 17 | #if TRACE_RESOURCES 18 | let _ = Resources.incrementTotal() 19 | #endif 20 | _eventHandler = eventHandler 21 | } 22 | 23 | override func onCore(_ event: Event) { 24 | return _eventHandler(event) 25 | } 26 | 27 | #if TRACE_RESOURCES 28 | deinit { 29 | let _ = Resources.decrementTotal() 30 | } 31 | #endif 32 | } 33 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ObserverBase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObserverBase.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/15/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | class ObserverBase : Disposable, ObserverType { 10 | typealias E = ElementType 11 | 12 | private var _isStopped: AtomicInt = 0 13 | 14 | func on(_ event: Event) { 15 | switch event { 16 | case .next: 17 | if _isStopped == 0 { 18 | onCore(event) 19 | } 20 | case .error, .completed: 21 | 22 | if !AtomicCompareAndSwap(0, 1, &_isStopped) { 23 | return 24 | } 25 | 26 | onCore(event) 27 | } 28 | } 29 | 30 | func onCore(_ event: Event) { 31 | abstractMethod() 32 | } 33 | 34 | func dispose() { 35 | _ = AtomicCompareAndSwap(0, 1, &_isStopped) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /smck/Parser/ParsingObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParsingObject.swift 3 | // SMCheckProjectCL 4 | // 5 | // Created by didi on 2017/3/10. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ParsingObject { 12 | class func parsing(tokens:[String], file:File) -> Observable { 13 | return Observable.create({ (observer) -> Disposable in 14 | for tk in tokens { 15 | //正常情况 16 | guard let obj = file.importObjects[tk] else { 17 | continue 18 | } 19 | guard let _ = file.usedObjects[tk] else { 20 | //记录使用过的类 21 | file.usedObjects[tk] = obj 22 | observer.on(.next(obj)) 23 | continue 24 | } 25 | } 26 | observer.on(.completed) 27 | return Disposables.create {} 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Lock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Lock.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/31/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | protocol Lock { 10 | func lock() 11 | func unlock() 12 | } 13 | 14 | // https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000321.html 15 | typealias SpinLock = RecursiveLock 16 | 17 | extension RecursiveLock : Lock { 18 | @inline(__always) 19 | final func performLocked(_ action: () -> Void) { 20 | lock(); defer { unlock() } 21 | action() 22 | } 23 | 24 | @inline(__always) 25 | final func calculateLocked(_ action: () -> T) -> T { 26 | lock(); defer { unlock() } 27 | return action() 28 | } 29 | 30 | @inline(__always) 31 | final func calculateLockedOrFail(_ action: () throws -> T) throws -> T { 32 | lock(); defer { unlock() } 33 | let result = try action() 34 | return result 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Observable+Debug.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Observable+Debug.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 5/2/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | // MARK: debug 10 | 11 | extension ObservableType { 12 | 13 | /** 14 | Prints received events for all observers on standard output. 15 | 16 | - seealso: [do operator on reactivex.io](http://reactivex.io/documentation/operators/do.html) 17 | 18 | - parameter identifier: Identifier that is printed together with event description to standard output. 19 | - parameter trimOutput: Should output be trimmed to max 40 characters. 20 | - returns: An observable sequence whose events are printed to standard output. 21 | */ 22 | public func debug(_ identifier: String? = nil, trimOutput: Bool = false, file: String = #file, line: UInt = #line, function: String = #function) 23 | -> Observable { 24 | return Debug(source: self, identifier: identifier, trimOutput: trimOutput, file: file, line: line, function: function) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/BooleanDisposable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BooleanDisposable.swift 3 | // RxSwift 4 | // 5 | // Created by Junior B. on 10/29/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents a disposable resource that can be checked for disposal status. 10 | public final class BooleanDisposable : Disposable, Cancelable { 11 | 12 | internal static let BooleanDisposableTrue = BooleanDisposable(isDisposed: true) 13 | private var _isDisposed = false 14 | 15 | /// Initializes a new instance of the `BooleanDisposable` class 16 | public init() { 17 | } 18 | 19 | /// Initializes a new instance of the `BooleanDisposable` class with given value 20 | public init(isDisposed: Bool) { 21 | self._isDisposed = isDisposed 22 | } 23 | 24 | /// - returns: Was resource disposed. 25 | public var isDisposed: Bool { 26 | return _isDisposed 27 | } 28 | 29 | /// Sets the status to disposed, which can be observer through the `isDisposed` property. 30 | public func dispose() { 31 | _isDisposed = true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /smck/Global/SeekFolderFiles.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SeekFolderFiles.swift 3 | // SMCheckProjectCL 4 | // 5 | // Created by daiming on 2017/3/7. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class SeekFolderFiles { 12 | 13 | class func seekWith(_ folderPath:String, matchingExtension:[String] = ["m","h","mm"]) -> [String] { 14 | let fileFolderPath = folderPath 15 | let fileFolderStringPath = fileFolderPath.replacingOccurrences(of: "file://", with: "") 16 | let fileManager = FileManager.default; 17 | //深度遍历 18 | let enumeratorAtPath = fileManager.enumerator(atPath: fileFolderStringPath) 19 | //过滤文件后缀 20 | let filterPath = NSArray(array: (enumeratorAtPath?.allObjects)!).pathsMatchingExtensions(matchingExtension) 21 | 22 | let rePaths = filterPath.map { (aPath) -> String in 23 | let fullPath = folderPath 24 | let nsFullPath = folderPath as NSString 25 | var slash = "/" 26 | if nsFullPath.lastPathComponent == slash { 27 | slash = "" 28 | } 29 | return "file://".appending(fullPath.appending(slash + aPath)) 30 | } 31 | return rePaths 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /smck/Parser/ParsingMacro.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParsingMacro.swift 3 | // SMCheckProject 4 | // 5 | // Created by daiming on 2017/2/22. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ParsingMacro { 12 | class func parsing(line:String) -> Macro { 13 | var macro = Macro() 14 | let aLine = line.replacingOccurrences(of: Sb.defineStr, with: "") 15 | let tokens = ParsingBase.createOCTokens(conent: aLine) 16 | guard let name = tokens.first else { 17 | return macro 18 | } 19 | macro.name = name 20 | macro.tokens = tokens 21 | return macro 22 | } 23 | //获取宏中所需的东西 24 | class func parsing(aMac:Macro, file:File) -> Observable { 25 | return Observable.create({ (observer) -> Disposable in 26 | 27 | _ = ParsingObject.parsing(tokens: aMac.tokens, file: file).subscribe(onNext: { result in 28 | if result is Object { 29 | let obj = result as! Object 30 | observer.on(.next(obj)) 31 | } 32 | }) 33 | observer.on(.completed) 34 | return Disposables.create {} 35 | }) 36 | } 37 | //获取宏中用到的字符串 38 | } 39 | -------------------------------------------------------------------------------- /smck/Parser/JSSb.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JSSb.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/5/2. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class JSSb { 12 | public static let rBktL = "(" 13 | public static let rBktR = ")" 14 | public static let bktL = "[" 15 | public static let bktR = "]" 16 | public static let braceL = "{" 17 | public static let braceR = "}" 18 | public static let comma = "," 19 | public static let colon = ":" 20 | public static let dot = "." 21 | public static let add = "+" 22 | public static let minus = "-" 23 | public static let tilde = "~" 24 | public static let excMk = "!" 25 | public static let asterisk = "*" 26 | public static let percent = "%" 27 | public static let agBktL = "<" 28 | public static let agBktR = ">" 29 | public static let equal = "=" 30 | public static let and = "&" 31 | public static let upArrow = "^" 32 | public static let pipe = "|" 33 | public static let qM = "?" 34 | public static let semicolon = ";" 35 | 36 | //keywords 37 | //this new delete void typeof instanceof var if else do while for in continue break return with switch case default throw try catch finally function import 38 | } 39 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Observable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Observable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/8/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// A type-erased `ObservableType`. 10 | /// 11 | /// It represents a push style sequence. 12 | public class Observable : ObservableType { 13 | /// Type of elements in sequence. 14 | public typealias E = Element 15 | 16 | init() { 17 | #if TRACE_RESOURCES 18 | let _ = Resources.incrementTotal() 19 | #endif 20 | } 21 | 22 | public func subscribe(_ observer: O) -> Disposable where O.E == E { 23 | abstractMethod() 24 | } 25 | 26 | public func asObservable() -> Observable { 27 | return self 28 | } 29 | 30 | deinit { 31 | #if TRACE_RESOURCES 32 | let _ = Resources.decrementTotal() 33 | #endif 34 | } 35 | 36 | // this is kind of ugly I know :( 37 | // Swift compiler reports "Not supported yet" when trying to override protocol extensions, so ¯\_(ツ)_/¯ 38 | 39 | /// Optimizations for map operator 40 | internal func composeMap(_ selector: @escaping (Element) throws -> R) -> Observable { 41 | return Map(source: self, transform: selector) 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ObserverType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObserverType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/8/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Supports push-style iteration over an observable sequence. 10 | public protocol ObserverType { 11 | /// The type of elements in sequence that observer can observe. 12 | associatedtype E 13 | 14 | /// Notify observer about sequence event. 15 | /// 16 | /// - parameter event: Event that occured. 17 | func on(_ event: Event) 18 | } 19 | 20 | /// Convenience API extensions to provide alternate next, error, completed events 21 | extension ObserverType { 22 | 23 | /// Convenience method equivalent to `on(.next(element: E))` 24 | /// 25 | /// - parameter element: Next element to send to observer(s) 26 | public final func onNext(_ element: E) { 27 | on(.next(element)) 28 | } 29 | 30 | /// Convenience method equivalent to `on(.completed)` 31 | public final func onCompleted() { 32 | on(.completed) 33 | } 34 | 35 | /// Convenience method equivalent to `on(.error(Swift.Error))` 36 | /// - parameter error: Swift.Error to send to observer(s) 37 | public final func onError(_ error: Swift.Error) { 38 | on(.error(error)) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ImmediateScheduler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImmediateScheduler.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/17/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents an object that schedules units of work to run immediately on the current thread. 10 | private final class ImmediateScheduler : ImmediateSchedulerType { 11 | 12 | private let _asyncLock = AsyncLock() 13 | 14 | /** 15 | Schedules an action to be executed immediatelly. 16 | 17 | In case `schedule` is called recursively from inside of `action` callback, scheduled `action` will be enqueued 18 | and executed after current `action`. (`AsyncLock` behavior) 19 | 20 | - parameter state: State passed to the action to be executed. 21 | - parameter action: Action to be executed. 22 | - returns: The disposable object used to cancel the scheduled action (best effort). 23 | */ 24 | func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { 25 | let disposable = SingleAssignmentDisposable() 26 | _asyncLock.invoke(AnonymousInvocable { 27 | if disposable.isDisposed { 28 | return 29 | } 30 | disposable.setDisposable(action(state)) 31 | }) 32 | 33 | return disposable 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/GroupedObservable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GroupedObservable.swift 3 | // RxSwift 4 | // 5 | // Created by Tomi Koskinen on 01/12/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents an observable sequence of elements that have a common key. 10 | public struct GroupedObservable : ObservableType { 11 | public typealias E = Element 12 | 13 | /// Gets the common key. 14 | public let key: Key 15 | 16 | private let source: Observable 17 | 18 | /// Initializes grouped observable sequence with key and source observable sequence. 19 | /// 20 | /// - parameter key: Grouped observable sequence key 21 | /// - parameter source: Observable sequence that represents sequence of elements for the key 22 | /// - returns: Grouped observable sequence of elements for the specific key 23 | public init(key: Key, source: Observable) { 24 | self.key = key 25 | self.source = source 26 | } 27 | 28 | /// Subscribes `observer` to receive events for this sequence. 29 | public func subscribe(_ observer: O) -> Disposable where O.E == E { 30 | return self.source.subscribe(observer) 31 | } 32 | 33 | /// Converts `self` to `Observable` sequence. 34 | public func asObservable() -> Observable { 35 | return source 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Repeat.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Repeat.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 9/13/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class RepeatElement : Producer { 10 | fileprivate let _element: Element 11 | fileprivate let _scheduler: ImmediateSchedulerType 12 | 13 | init(element: Element, scheduler: ImmediateSchedulerType) { 14 | _element = element 15 | _scheduler = scheduler 16 | } 17 | 18 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 19 | let sink = RepeatElementSink(parent: self, observer: observer, cancel: cancel) 20 | let subscription = sink.run() 21 | 22 | return (sink: sink, subscription: subscription) 23 | } 24 | } 25 | 26 | final class RepeatElementSink : Sink { 27 | typealias Parent = RepeatElement 28 | 29 | private let _parent: Parent 30 | 31 | init(parent: Parent, observer: O, cancel: Cancelable) { 32 | _parent = parent 33 | super.init(observer: observer, cancel: cancel) 34 | } 35 | 36 | func run() -> Disposable { 37 | return _parent._scheduler.scheduleRecursive(_parent._element) { e, recurse in 38 | self.forwardOn(.next(e)) 39 | recurse(e) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Bag+Rx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Bag+Rx.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/19/16. 6 | // Copyright © 2016 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | 10 | // MARK: forEach 11 | 12 | @inline(__always) 13 | func dispatch(_ bag: Bag<(Event) -> ()>, _ event: Event) { 14 | if bag._onlyFastPath { 15 | bag._value0?(event) 16 | return 17 | } 18 | 19 | let value0 = bag._value0 20 | let dictionary = bag._dictionary 21 | 22 | if let value0 = value0 { 23 | value0(event) 24 | } 25 | 26 | let pairs = bag._pairs 27 | for i in 0 ..< pairs.count { 28 | pairs[i].value(event) 29 | } 30 | 31 | if let dictionary = dictionary { 32 | for element in dictionary.values { 33 | element(event) 34 | } 35 | } 36 | } 37 | 38 | /// Dispatches `dispose` to all disposables contained inside bag. 39 | func disposeAll(in bag: Bag) { 40 | if bag._onlyFastPath { 41 | bag._value0?.dispose() 42 | return 43 | } 44 | 45 | let value0 = bag._value0 46 | let dictionary = bag._dictionary 47 | 48 | if let value0 = value0 { 49 | value0.dispose() 50 | } 51 | 52 | let pairs = bag._pairs 53 | for i in 0 ..< pairs.count { 54 | pairs[i].value.dispose() 55 | } 56 | 57 | if let dictionary = dictionary { 58 | for element in dictionary.values { 59 | element.dispose() 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/AddRef.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddRef.swift 3 | // RxSwift 4 | // 5 | // Created by Junior B. on 30/10/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class AddRefSink : Sink, ObserverType { 10 | typealias Element = O.E 11 | 12 | override init(observer: O, cancel: Cancelable) { 13 | super.init(observer: observer, cancel: cancel) 14 | } 15 | 16 | func on(_ event: Event) { 17 | switch event { 18 | case .next(_): 19 | forwardOn(event) 20 | case .completed, .error(_): 21 | forwardOn(event) 22 | dispose() 23 | } 24 | } 25 | } 26 | 27 | final class AddRef : Producer { 28 | typealias EventHandler = (Event) throws -> Void 29 | 30 | private let _source: Observable 31 | private let _refCount: RefCountDisposable 32 | 33 | init(source: Observable, refCount: RefCountDisposable) { 34 | _source = source 35 | _refCount = refCount 36 | } 37 | 38 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 39 | let releaseDisposable = _refCount.retain() 40 | let sink = AddRefSink(observer: observer, cancel: cancel) 41 | let subscription = Disposables.create(releaseDisposable, _source.subscribe(sink)) 42 | 43 | return (sink: sink, subscription: subscription) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ToArray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ToArray.swift 3 | // RxSwift 4 | // 5 | // Created by Junior B. on 20/10/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class ToArraySink : Sink, ObserverType where O.E == [SourceType] { 10 | typealias Parent = ToArray 11 | 12 | let _parent: Parent 13 | var _list = Array() 14 | 15 | init(parent: Parent, observer: O, cancel: Cancelable) { 16 | _parent = parent 17 | 18 | super.init(observer: observer, cancel: cancel) 19 | } 20 | 21 | func on(_ event: Event) { 22 | switch event { 23 | case .next(let value): 24 | self._list.append(value) 25 | case .error(let e): 26 | forwardOn(.error(e)) 27 | self.dispose() 28 | case .completed: 29 | forwardOn(.next(_list)) 30 | forwardOn(.completed) 31 | self.dispose() 32 | } 33 | } 34 | } 35 | 36 | final class ToArray : Producer<[SourceType]> { 37 | let _source: Observable 38 | 39 | init(source: Observable) { 40 | _source = source 41 | } 42 | 43 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == [SourceType] { 44 | let sink = ToArraySink(parent: self, observer: observer, cancel: cancel) 45 | let subscription = _source.subscribe(sink) 46 | return (sink: sink, subscription: subscription) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ImmediateSchedulerType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImmediateSchedulerType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 5/31/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents an object that immediately schedules units of work. 10 | public protocol ImmediateSchedulerType { 11 | /** 12 | Schedules an action to be executed immediatelly. 13 | 14 | - parameter state: State passed to the action to be executed. 15 | - parameter action: Action to be executed. 16 | - returns: The disposable object used to cancel the scheduled action (best effort). 17 | */ 18 | func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable 19 | } 20 | 21 | extension ImmediateSchedulerType { 22 | /** 23 | Schedules an action to be executed recursively. 24 | 25 | - parameter state: State passed to the action to be executed. 26 | - parameter action: Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in recursive invocation state. 27 | - returns: The disposable object used to cancel the scheduled action (best effort). 28 | */ 29 | public func scheduleRecursive(_ state: State, action: @escaping (_ state: State, _ recurse: (State) -> ()) -> ()) -> Disposable { 30 | let recursiveScheduler = RecursiveImmediateScheduler(action: action, scheduler: self) 31 | 32 | recursiveScheduler.schedule(state) 33 | 34 | return Disposables.create(with: recursiveScheduler.dispose) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/DelaySubscription.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DelaySubscription.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 6/14/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class DelaySubscriptionSink 10 | : Sink, ObserverType { 11 | typealias E = O.E 12 | typealias Parent = DelaySubscription 13 | 14 | private let _parent: Parent 15 | 16 | init(parent: Parent, observer: O, cancel: Cancelable) { 17 | _parent = parent 18 | super.init(observer: observer, cancel: cancel) 19 | } 20 | 21 | func on(_ event: Event) { 22 | forwardOn(event) 23 | if event.isStopEvent { 24 | dispose() 25 | } 26 | } 27 | 28 | } 29 | 30 | final class DelaySubscription: Producer { 31 | private let _source: Observable 32 | private let _dueTime: RxTimeInterval 33 | private let _scheduler: SchedulerType 34 | 35 | init(source: Observable, dueTime: RxTimeInterval, scheduler: SchedulerType) { 36 | _source = source 37 | _dueTime = dueTime 38 | _scheduler = scheduler 39 | } 40 | 41 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 42 | let sink = DelaySubscriptionSink(parent: self, observer: observer, cancel: cancel) 43 | let subscription = _scheduler.scheduleRelative((), dueTime: _dueTime) { _ in 44 | return self._source.subscribe(sink) 45 | } 46 | 47 | return (sink: sink, subscription: subscription) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/DefaultIfEmpty.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultIfEmpty.swift 3 | // RxSwift 4 | // 5 | // Created by sergdort on 23/12/2016. 6 | // Copyright © 2016 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class DefaultIfEmptySink: Sink, ObserverType { 10 | typealias E = O.E 11 | private let _default: E 12 | private var _isEmpty = true 13 | 14 | init(default: E, observer: O, cancel: Cancelable) { 15 | _default = `default` 16 | super.init(observer: observer, cancel: cancel) 17 | } 18 | 19 | func on(_ event: Event) { 20 | switch event { 21 | case .next(_): 22 | _isEmpty = false 23 | forwardOn(event) 24 | case .error(_): 25 | forwardOn(event) 26 | dispose() 27 | case .completed: 28 | if _isEmpty { 29 | forwardOn(.next(_default)) 30 | } 31 | forwardOn(.completed) 32 | dispose() 33 | } 34 | } 35 | } 36 | 37 | final class DefaultIfEmpty: Producer { 38 | private let _source: Observable 39 | private let _default: SourceType 40 | 41 | init(source: Observable, `default`: SourceType) { 42 | _source = source 43 | _default = `default` 44 | } 45 | 46 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == SourceType { 47 | let sink = DefaultIfEmptySink(default: _default, observer: observer, cancel: cancel) 48 | let subscription = _source.subscribe(sink) 49 | return (sink: sink, subscription: subscription) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /smck/Global/Sb.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Sb.swift 3 | // SMCheckProject 4 | // 5 | // Created by daiming on 2016/10/25. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class Sb { 12 | public static let add = "+" 13 | public static let minus = "-" 14 | public static let rBktL = "(" 15 | public static let rBktR = ")" 16 | public static let asterisk = "*" 17 | public static let colon = ":" 18 | public static let comma = "," 19 | public static let semicolon = ";" 20 | public static let divide = "/" 21 | public static let agBktL = "<" 22 | public static let agBktR = ">" 23 | public static let quotM = "\"" 24 | public static let pSign = "#" 25 | public static let braceL = "{" 26 | public static let braceR = "}" 27 | public static let bktL = "[" 28 | public static let bktR = "]" 29 | public static let qM = "?" 30 | public static let upArrow = "^" 31 | public static let at = "@" 32 | 33 | public static let atInteface = "@interface" 34 | public static let atImplementation = "@implementation" 35 | public static let atEnd = "@end" 36 | public static let atProtocol = "@protocol" 37 | public static let atOptional = "@optional" 38 | public static let atRequired = "@required" 39 | 40 | public static let atSelector = "@selector" 41 | public static let atProperty = "@property" 42 | 43 | public static let defineStr = "#define" 44 | public static let importStr = "#import" 45 | 46 | public static let implementationStr = "implementation" 47 | public static let endStr = "end" 48 | 49 | 50 | public static let space = " " 51 | public static let newLine = "\n" 52 | } 53 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Errors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Errors.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/28/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | let RxErrorDomain = "RxErrorDomain" 10 | let RxCompositeFailures = "RxCompositeFailures" 11 | 12 | /// Generic Rx error codes. 13 | public enum RxError 14 | : Swift.Error 15 | , CustomDebugStringConvertible { 16 | /// Unknown error occured. 17 | case unknown 18 | /// Performing an action on disposed object. 19 | case disposed(object: AnyObject) 20 | /// Aritmetic overflow error. 21 | case overflow 22 | /// Argument out of range error. 23 | case argumentOutOfRange 24 | /// Sequence doesn't contain any elements. 25 | case noElements 26 | /// Sequence contains more than one element. 27 | case moreThanOneElement 28 | /// Timeout error. 29 | case timeout 30 | } 31 | 32 | extension RxError { 33 | /// A textual representation of `self`, suitable for debugging. 34 | public var debugDescription: String { 35 | switch self { 36 | case .unknown: 37 | return "Unknown error occured." 38 | case .disposed(let object): 39 | return "Object `\(object)` was already disposed." 40 | case .overflow: 41 | return "Arithmetic overflow occured." 42 | case .argumentOutOfRange: 43 | return "Argument out of range." 44 | case .noElements: 45 | return "Sequence doesn't contain any elements." 46 | case .moreThanOneElement: 47 | return "Sequence contains more than one element." 48 | case .timeout: 49 | return "Sequence timeout." 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ScheduledDisposable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScheduledDisposable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 6/13/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | private let disposeScheduledDisposable: (ScheduledDisposable) -> Disposable = { sd in 10 | sd.disposeInner() 11 | return Disposables.create() 12 | } 13 | 14 | /// Represents a disposable resource whose disposal invocation will be scheduled on the specified scheduler. 15 | public final class ScheduledDisposable : Cancelable { 16 | public let scheduler: ImmediateSchedulerType 17 | 18 | private var _isDisposed: AtomicInt = 0 19 | 20 | // state 21 | private var _disposable: Disposable? 22 | 23 | /// - returns: Was resource disposed. 24 | public var isDisposed: Bool { 25 | return _isDisposed == 1 26 | } 27 | 28 | /** 29 | Initializes a new instance of the `ScheduledDisposable` that uses a `scheduler` on which to dispose the `disposable`. 30 | 31 | - parameter scheduler: Scheduler where the disposable resource will be disposed on. 32 | - parameter disposable: Disposable resource to dispose on the given scheduler. 33 | */ 34 | public init(scheduler: ImmediateSchedulerType, disposable: Disposable) { 35 | self.scheduler = scheduler 36 | _disposable = disposable 37 | } 38 | 39 | /// Disposes the wrapped disposable on the provided scheduler. 40 | public func dispose() { 41 | let _ = scheduler.schedule(self, action: disposeScheduledDisposable) 42 | } 43 | 44 | func disposeInner() { 45 | if AtomicCompareAndSwap(0, 1, &_isDisposed) { 46 | _disposable!.dispose() 47 | _disposable = nil 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /smck/Parser/ParsingProperty.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParsingProperty.swift 3 | // SMCheckProject 4 | // 5 | // Created by daiming on 2017/2/23. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ParsingProperty { 12 | class func parsing(tokens:Array) -> Property { 13 | var aProperty = Property() 14 | var inBktTf = false 15 | var inTypeTf = false 16 | var inNameTf = false 17 | var setName = "" 18 | 19 | for tk in tokens { 20 | //处理设置set 21 | if tk == Sb.rBktL && !inBktTf { 22 | inBktTf = true 23 | } else if tk == Sb.comma && inBktTf { 24 | aProperty.sets.append(setName) 25 | } else if tk == Sb.rBktR && inBktTf { 26 | aProperty.sets.append(setName) 27 | inBktTf = false 28 | setName = "" 29 | inTypeTf = true 30 | continue 31 | } else if inBktTf { 32 | setName = tk 33 | } 34 | //处理类型和属性名 35 | if inTypeTf && !inNameTf && (tk != Sb.agBktL || tk != Sb.agBktR) { 36 | aProperty.type = tk 37 | inNameTf = true 38 | continue 39 | } 40 | if inTypeTf && tk == Sb.agBktL { 41 | inNameTf = false 42 | } 43 | if inTypeTf && tk == Sb.agBktR { 44 | inNameTf = true 45 | continue 46 | } 47 | if inNameTf && tk != Sb.asterisk && tk != Sb.semicolon{ 48 | aProperty.name = tk 49 | } 50 | 51 | } 52 | 53 | return aProperty 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /smck/Parser/ParsingImport.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParsingImport.swift 3 | // SMCheckProject 4 | // 5 | // Created by daiming on 2017/2/22. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ParsingImport { 12 | class func parsing(tokens:Array) -> Import { 13 | var aImport = Import() 14 | //处理#import "file.h" 15 | var inQuot = false 16 | var fileName = "" 17 | 18 | //处理#import 19 | var inBkt = false 20 | var getLibNameTf = false 21 | var libName = "" 22 | 23 | for tk in tokens { 24 | //引号 25 | if tk == Sb.quotM && !inQuot { 26 | inQuot = true 27 | } else if tk == Sb.quotM && inQuot { 28 | inQuot = false 29 | aImport.fileName = fileName 30 | } else if inQuot { 31 | fileName += tk 32 | } 33 | //中括号 34 | if tk == Sb.agBktL && !inBkt { 35 | inBkt = true 36 | } else if tk == Sb.divide && inBkt && !getLibNameTf { 37 | aImport.libName = libName 38 | getLibNameTf = true 39 | } else if tk == Sb.agBktR && getLibNameTf { 40 | aImport.fileName = fileName 41 | //clean 42 | inBkt = false 43 | getLibNameTf = false 44 | fileName = "" 45 | libName = "" 46 | } else if inBkt && getLibNameTf { 47 | fileName += tk 48 | } else if inBkt && !getLibNameTf { 49 | libName += tk 50 | } 51 | 52 | } 53 | 54 | return aImport 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/BinaryDisposable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BinaryDisposable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 6/12/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents two disposable resources that are disposed together. 10 | private final class BinaryDisposable : DisposeBase, Cancelable { 11 | 12 | private var _isDisposed: AtomicInt = 0 13 | 14 | // state 15 | private var _disposable1: Disposable? 16 | private var _disposable2: Disposable? 17 | 18 | /// - returns: Was resource disposed. 19 | var isDisposed: Bool { 20 | return _isDisposed > 0 21 | } 22 | 23 | /// Constructs new binary disposable from two disposables. 24 | /// 25 | /// - parameter disposable1: First disposable 26 | /// - parameter disposable2: Second disposable 27 | init(_ disposable1: Disposable, _ disposable2: Disposable) { 28 | _disposable1 = disposable1 29 | _disposable2 = disposable2 30 | super.init() 31 | } 32 | 33 | /// Calls the disposal action if and only if the current instance hasn't been disposed yet. 34 | /// 35 | /// After invoking disposal action, disposal action will be dereferenced. 36 | func dispose() { 37 | if AtomicCompareAndSwap(0, 1, &_isDisposed) { 38 | _disposable1?.dispose() 39 | _disposable2?.dispose() 40 | _disposable1 = nil 41 | _disposable2 = nil 42 | } 43 | } 44 | } 45 | 46 | extension Disposables { 47 | 48 | /// Creates a disposable with the given disposables. 49 | public static func create(_ disposable1: Disposable, _ disposable2: Disposable) -> Cancelable { 50 | return BinaryDisposable(disposable1, disposable2) 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Sequence.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Sequence.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 11/14/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class ObservableSequenceSink : Sink where S.Iterator.Element == O.E { 10 | typealias Parent = ObservableSequence 11 | 12 | private let _parent: Parent 13 | 14 | init(parent: Parent, observer: O, cancel: Cancelable) { 15 | _parent = parent 16 | super.init(observer: observer, cancel: cancel) 17 | } 18 | 19 | func run() -> Disposable { 20 | return _parent._scheduler.scheduleRecursive((_parent._elements.makeIterator(), _parent._elements)) { (iterator, recurse) in 21 | var mutableIterator = iterator 22 | if let next = mutableIterator.0.next() { 23 | self.forwardOn(.next(next)) 24 | recurse(mutableIterator) 25 | } 26 | else { 27 | self.forwardOn(.completed) 28 | self.dispose() 29 | } 30 | } 31 | } 32 | } 33 | 34 | final class ObservableSequence : Producer { 35 | fileprivate let _elements: S 36 | fileprivate let _scheduler: ImmediateSchedulerType 37 | 38 | init(elements: S, scheduler: ImmediateSchedulerType) { 39 | _elements = elements 40 | _scheduler = scheduler 41 | } 42 | 43 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == E { 44 | let sink = ObservableSequenceSink(parent: self, observer: observer, cancel: cancel) 45 | let subscription = sink.run() 46 | return (sink: sink, subscription: subscription) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ObservableType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObservableType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 8/8/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents a push style sequence. 10 | public protocol ObservableType : ObservableConvertibleType { 11 | /// Type of elements in sequence. 12 | associatedtype E 13 | 14 | /** 15 | Subscribes `observer` to receive events for this sequence. 16 | 17 | ### Grammar 18 | 19 | **Next\* (Error | Completed)?** 20 | 21 | * sequences can produce zero or more elements so zero or more `Next` events can be sent to `observer` 22 | * once an `Error` or `Completed` event is sent, the sequence terminates and can't produce any other elements 23 | 24 | It is possible that events are sent from different threads, but no two events can be sent concurrently to 25 | `observer`. 26 | 27 | ### Resource Management 28 | 29 | When sequence sends `Complete` or `Error` event all internal resources that compute sequence elements 30 | will be freed. 31 | 32 | To cancel production of sequence elements and free resources immediatelly, call `dispose` on returned 33 | subscription. 34 | 35 | - returns: Subscription for `observer` that can be used to cancel production of sequence elements and free resources. 36 | */ 37 | func subscribe(_ observer: O) -> Disposable where O.E == E 38 | } 39 | 40 | extension ObservableType { 41 | 42 | /// Default implementation of converting `ObservableType` to `Observable`. 43 | public func asObservable() -> Observable { 44 | // temporary workaround 45 | //return Observable.create(subscribe: self.subscribe) 46 | return Observable.create { o in 47 | return self.subscribe(o) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Deferred.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Deferred.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 4/19/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class DeferredSink : Sink, ObserverType where S.E == O.E { 10 | typealias E = O.E 11 | 12 | private let _observableFactory: () throws -> S 13 | 14 | init(observableFactory: @escaping () throws -> S, observer: O, cancel: Cancelable) { 15 | _observableFactory = observableFactory 16 | super.init(observer: observer, cancel: cancel) 17 | } 18 | 19 | func run() -> Disposable { 20 | do { 21 | let result = try _observableFactory() 22 | return result.subscribe(self) 23 | } 24 | catch let e { 25 | forwardOn(.error(e)) 26 | dispose() 27 | return Disposables.create() 28 | } 29 | } 30 | 31 | func on(_ event: Event) { 32 | forwardOn(event) 33 | 34 | switch event { 35 | case .next: 36 | break 37 | case .error: 38 | dispose() 39 | case .completed: 40 | dispose() 41 | } 42 | } 43 | } 44 | 45 | final class Deferred : Producer { 46 | typealias Factory = () throws -> S 47 | 48 | private let _observableFactory : Factory 49 | 50 | init(observableFactory: @escaping Factory) { 51 | _observableFactory = observableFactory 52 | } 53 | 54 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == S.E { 55 | let sink = DeferredSink(observableFactory: _observableFactory, observer: observer, cancel: cancel) 56 | let subscription = sink.run() 57 | return (sink: sink, subscription: subscription) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Range.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Range.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 9/13/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class RangeProducer : Producer { 10 | fileprivate let _start: E 11 | fileprivate let _count: E 12 | fileprivate let _scheduler: ImmediateSchedulerType 13 | 14 | init(start: E, count: E, scheduler: ImmediateSchedulerType) { 15 | if count < 0 { 16 | rxFatalError("count can't be negative") 17 | } 18 | 19 | if start &+ (count - 1) < start { 20 | rxFatalError("overflow of count") 21 | } 22 | 23 | _start = start 24 | _count = count 25 | _scheduler = scheduler 26 | } 27 | 28 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == E { 29 | let sink = RangeSink(parent: self, observer: observer, cancel: cancel) 30 | let subscription = sink.run() 31 | return (sink: sink, subscription: subscription) 32 | } 33 | } 34 | 35 | final class RangeSink : Sink where O.E: SignedInteger { 36 | typealias Parent = RangeProducer 37 | 38 | private let _parent: Parent 39 | 40 | init(parent: Parent, observer: O, cancel: Cancelable) { 41 | _parent = parent 42 | super.init(observer: observer, cancel: cancel) 43 | } 44 | 45 | func run() -> Disposable { 46 | return _parent._scheduler.scheduleRecursive(0 as O.E) { i, recurse in 47 | if i < self._parent._count { 48 | self.forwardOn(.next(self._parent._start + i)) 49 | recurse(i + 1) 50 | } 51 | else { 52 | self.forwardOn(.completed) 53 | self.dispose() 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Filter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Filter.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/17/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class FilterSink: Sink, ObserverType { 10 | typealias Predicate = (Element) throws -> Bool 11 | typealias Element = O.E 12 | 13 | private let _predicate: Predicate 14 | 15 | init(predicate: @escaping Predicate, observer: O, cancel: Cancelable) { 16 | _predicate = predicate 17 | super.init(observer: observer, cancel: cancel) 18 | } 19 | 20 | func on(_ event: Event) { 21 | switch event { 22 | case .next(let value): 23 | do { 24 | let satisfies = try _predicate(value) 25 | if satisfies { 26 | forwardOn(.next(value)) 27 | } 28 | } 29 | catch let e { 30 | forwardOn(.error(e)) 31 | dispose() 32 | } 33 | case .completed, .error: 34 | forwardOn(event) 35 | dispose() 36 | } 37 | } 38 | } 39 | 40 | final class Filter : Producer { 41 | typealias Predicate = (Element) throws -> Bool 42 | 43 | private let _source: Observable 44 | private let _predicate: Predicate 45 | 46 | init(source: Observable, predicate: @escaping Predicate) { 47 | _source = source 48 | _predicate = predicate 49 | } 50 | 51 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 52 | let sink = FilterSink(predicate: _predicate, observer: observer, cancel: cancel) 53 | let subscription = _source.subscribe(sink) 54 | return (sink: sink, subscription: subscription) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/TakeLast.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TakeLast.swift 3 | // RxSwift 4 | // 5 | // Created by Tomi Koskinen on 25/10/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class TakeLastSink : Sink, ObserverType { 10 | typealias E = O.E 11 | typealias Parent = TakeLast 12 | 13 | private let _parent: Parent 14 | 15 | private var _elements: Queue 16 | 17 | init(parent: Parent, observer: O, cancel: Cancelable) { 18 | _parent = parent 19 | _elements = Queue(capacity: parent._count + 1) 20 | super.init(observer: observer, cancel: cancel) 21 | } 22 | 23 | func on(_ event: Event) { 24 | switch event { 25 | case .next(let value): 26 | _elements.enqueue(value) 27 | if _elements.count > self._parent._count { 28 | let _ = _elements.dequeue() 29 | } 30 | case .error: 31 | forwardOn(event) 32 | dispose() 33 | case .completed: 34 | for e in _elements { 35 | forwardOn(.next(e)) 36 | } 37 | forwardOn(.completed) 38 | dispose() 39 | } 40 | } 41 | } 42 | 43 | final class TakeLast: Producer { 44 | fileprivate let _source: Observable 45 | fileprivate let _count: Int 46 | 47 | init(source: Observable, count: Int) { 48 | if count < 0 { 49 | rxFatalError("count can't be negative") 50 | } 51 | _source = source 52 | _count = count 53 | } 54 | 55 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 56 | let sink = TakeLastSink(parent: self, observer: observer, cancel: cancel) 57 | let subscription = _source.subscribe(sink) 58 | return (sink: sink, subscription: subscription) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/OperationQueueScheduler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OperationQueueScheduler.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 4/4/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | import class Foundation.OperationQueue 10 | import class Foundation.BlockOperation 11 | import Dispatch 12 | 13 | /// Abstracts the work that needs to be performed on a specific `NSOperationQueue`. 14 | /// 15 | /// This scheduler is suitable for cases when there is some bigger chunk of work that needs to be performed in background and you want to fine tune concurrent processing using `maxConcurrentOperationCount`. 16 | public class OperationQueueScheduler: ImmediateSchedulerType { 17 | public let operationQueue: OperationQueue 18 | 19 | /// Constructs new instance of `OperationQueueScheduler` that performs work on `operationQueue`. 20 | /// 21 | /// - parameter operationQueue: Operation queue targeted to perform work on. 22 | public init(operationQueue: OperationQueue) { 23 | self.operationQueue = operationQueue 24 | } 25 | 26 | /** 27 | Schedules an action to be executed recursively. 28 | 29 | - parameter state: State passed to the action to be executed. 30 | - parameter action: Action to execute recursively. The last parameter passed to the action is used to trigger recursive scheduling of the action, passing in recursive invocation state. 31 | - returns: The disposable object used to cancel the scheduled action (best effort). 32 | */ 33 | public func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { 34 | let cancel = SingleAssignmentDisposable() 35 | 36 | let operation = BlockOperation { 37 | if cancel.isDisposed { 38 | return 39 | } 40 | 41 | 42 | cancel.setDisposable(action(state)) 43 | } 44 | 45 | self.operationQueue.addOperation(operation) 46 | 47 | return cancel 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Just.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Just.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 8/30/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class JustScheduledSink : Sink { 10 | typealias Parent = JustScheduled 11 | 12 | private let _parent: Parent 13 | 14 | init(parent: Parent, observer: O, cancel: Cancelable) { 15 | _parent = parent 16 | super.init(observer: observer, cancel: cancel) 17 | } 18 | 19 | func run() -> Disposable { 20 | let scheduler = _parent._scheduler 21 | return scheduler.schedule(_parent._element) { element in 22 | self.forwardOn(.next(element)) 23 | return scheduler.schedule(()) { _ in 24 | self.forwardOn(.completed) 25 | self.dispose() 26 | return Disposables.create() 27 | } 28 | } 29 | } 30 | } 31 | 32 | final class JustScheduled : Producer { 33 | fileprivate let _scheduler: ImmediateSchedulerType 34 | fileprivate let _element: Element 35 | 36 | init(element: Element, scheduler: ImmediateSchedulerType) { 37 | _scheduler = scheduler 38 | _element = element 39 | } 40 | 41 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == E { 42 | let sink = JustScheduledSink(parent: self, observer: observer, cancel: cancel) 43 | let subscription = sink.run() 44 | return (sink: sink, subscription: subscription) 45 | } 46 | } 47 | 48 | final class Just : Producer { 49 | private let _element: Element 50 | 51 | init(element: Element) { 52 | _element = element 53 | } 54 | 55 | override func subscribe(_ observer: O) -> Disposable where O.E == Element { 56 | observer.on(.next(_element)) 57 | observer.on(.completed) 58 | return Disposables.create() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /smck/Parser/JSLexer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JSLexer.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/5/2. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class JSLexer { 12 | let input: String 13 | var index: String.Index 14 | 15 | init(input: String) { 16 | // 17 | self.input = input 18 | self.index = input.startIndex 19 | } 20 | 21 | public func lex() -> [String] { 22 | var tks = [String]() 23 | while let tk = advanceToNextToken() { 24 | if tk == " " || tk == "" { 25 | } else { 26 | tks.append(tk) 27 | } 28 | } 29 | return tks 30 | } 31 | 32 | func advanceToNextToken() -> String? { 33 | //末尾检测 34 | guard currentChar != nil else { 35 | return nil 36 | } 37 | let keyMap = [JSSb.rBktL,JSSb.rBktR,JSSb.bktL,JSSb.bktR,JSSb.braceL,JSSb.braceR,JSSb.comma,JSSb.colon,JSSb.dot,JSSb.add,JSSb.minus,JSSb.tilde,JSSb.excMk,JSSb.asterisk,JSSb.percent,JSSb.agBktL,JSSb.equal,JSSb.and,JSSb.upArrow,JSSb.pipe,JSSb.qM,JSSb.semicolon," "] 38 | let currentStr = currentChar?.description 39 | var str = "" 40 | var quite = false 41 | 42 | if keyMap.contains(currentStr!) { 43 | advanceIndex() 44 | return currentStr! 45 | } else { 46 | while let char = currentChar, !quite { 47 | let charStr = char.description 48 | if keyMap.contains(charStr) { 49 | quite = true 50 | } else { 51 | str.characters.append(char) 52 | advanceIndex() 53 | } 54 | } 55 | return str 56 | } 57 | } 58 | 59 | /*-----------*/ 60 | var currentChar: Character? { 61 | return index < input.endIndex ? input[index] : nil 62 | } 63 | func advanceIndex() { 64 | input.characters.formIndex(after: &index) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Rx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Rx.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/14/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | #if TRACE_RESOURCES 10 | fileprivate var resourceCount: AtomicInt = 0 11 | 12 | /// Resource utilization information 13 | public struct Resources { 14 | /// Counts internal Rx resource allocations (Observables, Observers, Disposables, etc.). This provides a simple way to detect leaks during development. 15 | public static var total: Int32 { 16 | return resourceCount.valueSnapshot() 17 | } 18 | 19 | /// Increments `Resources.total` resource count. 20 | /// 21 | /// - returns: New resource count 22 | public static func incrementTotal() -> Int32 { 23 | return AtomicIncrement(&resourceCount) 24 | } 25 | 26 | /// Decrements `Resources.total` resource count 27 | /// 28 | /// - returns: New resource count 29 | public static func decrementTotal() -> Int32 { 30 | return AtomicDecrement(&resourceCount) 31 | } 32 | } 33 | #endif 34 | 35 | /// Swift does not implement abstract methods. This method is used as a runtime check to ensure that methods which intended to be abstract (i.e., they should be implemented in subclasses) are not called directly on the superclass. 36 | func abstractMethod() -> Swift.Never { 37 | rxFatalError("Abstract method") 38 | } 39 | 40 | func rxFatalError(_ lastMessage: String) -> Swift.Never { 41 | // The temptation to comment this line is great, but please don't, it's for your own good. The choice is yours. 42 | fatalError(lastMessage) 43 | } 44 | 45 | func incrementChecked(_ i: inout Int) throws -> Int { 46 | if i == Int.max { 47 | throw RxError.overflow 48 | } 49 | defer { i += 1 } 50 | return i 51 | } 52 | 53 | func decrementChecked(_ i: inout Int) throws -> Int { 54 | if i == Int.min { 55 | throw RxError.overflow 56 | } 57 | defer { i -= 1 } 58 | return i 59 | } 60 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Concat.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Concat.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/21/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | 10 | final class ConcatSink 11 | : TailRecursiveSink 12 | , ObserverType where S.Iterator.Element : ObservableConvertibleType, S.Iterator.Element.E == O.E { 13 | typealias Element = O.E 14 | 15 | override init(observer: O, cancel: Cancelable) { 16 | super.init(observer: observer, cancel: cancel) 17 | } 18 | 19 | func on(_ event: Event){ 20 | switch event { 21 | case .next: 22 | forwardOn(event) 23 | case .error: 24 | forwardOn(event) 25 | dispose() 26 | case .completed: 27 | schedule(.moveNext) 28 | } 29 | } 30 | 31 | override func subscribeToNext(_ source: Observable) -> Disposable { 32 | return source.subscribe(self) 33 | } 34 | 35 | override func extract(_ observable: Observable) -> SequenceGenerator? { 36 | if let source = observable as? Concat { 37 | return (source._sources.makeIterator(), source._count) 38 | } 39 | else { 40 | return nil 41 | } 42 | } 43 | } 44 | 45 | final class Concat : Producer where S.Iterator.Element : ObservableConvertibleType { 46 | typealias Element = S.Iterator.Element.E 47 | 48 | fileprivate let _sources: S 49 | fileprivate let _count: IntMax? 50 | 51 | init(sources: S, count: IntMax?) { 52 | _sources = sources 53 | _count = count 54 | } 55 | 56 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 57 | let sink = ConcatSink(observer: observer, cancel: cancel) 58 | let subscription = sink.run((_sources.makeIterator(), _count)) 59 | return (sink: sink, subscription: subscription) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Reactive.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Reactive.swift 3 | // RxSwift 4 | // 5 | // Created by Yury Korolev on 5/2/16. 6 | // Copyright © 2016 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /** 10 | Use `Reactive` proxy as customization point for constrained protocol extensions. 11 | 12 | General pattern would be: 13 | 14 | // 1. Extend Reactive protocol with constrain on Base 15 | // Read as: Reactive Extension where Base is a SomeType 16 | extension Reactive where Base: SomeType { 17 | // 2. Put any specific reactive extension for SomeType here 18 | } 19 | 20 | With this approach we can have more specialized methods and properties using 21 | `Base` and not just specialized on common base type. 22 | 23 | */ 24 | 25 | public struct Reactive { 26 | /// Base object to extend. 27 | public let base: Base 28 | 29 | /// Creates extensions with base object. 30 | /// 31 | /// - parameter base: Base object. 32 | public init(_ base: Base) { 33 | self.base = base 34 | } 35 | } 36 | 37 | /// A type that has reactive extensions. 38 | public protocol ReactiveCompatible { 39 | /// Extended type 40 | associatedtype CompatibleType 41 | 42 | /// Reactive extensions. 43 | static var rx: Reactive.Type { get set } 44 | 45 | /// Reactive extensions. 46 | var rx: Reactive { get set } 47 | } 48 | 49 | extension ReactiveCompatible { 50 | /// Reactive extensions. 51 | public static var rx: Reactive.Type { 52 | get { 53 | return Reactive.self 54 | } 55 | set { 56 | // this enables using Reactive to "mutate" base type 57 | } 58 | } 59 | 60 | /// Reactive extensions. 61 | public var rx: Reactive { 62 | get { 63 | return Reactive(self) 64 | } 65 | set { 66 | // this enables using Reactive to "mutate" base object 67 | } 68 | } 69 | } 70 | 71 | import class Foundation.NSObject 72 | 73 | /// Extend NSObject with `rx` proxy. 74 | extension NSObject: ReactiveCompatible { } 75 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Do.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Do.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/21/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class DoSink : Sink, ObserverType { 10 | typealias Element = O.E 11 | typealias Parent = Do 12 | 13 | private let _parent: Parent 14 | 15 | init(parent: Parent, observer: O, cancel: Cancelable) { 16 | _parent = parent 17 | super.init(observer: observer, cancel: cancel) 18 | } 19 | 20 | func on(_ event: Event) { 21 | do { 22 | try _parent._eventHandler(event) 23 | forwardOn(event) 24 | if event.isStopEvent { 25 | dispose() 26 | } 27 | } 28 | catch let error { 29 | forwardOn(.error(error)) 30 | dispose() 31 | } 32 | } 33 | } 34 | 35 | final class Do : Producer { 36 | typealias EventHandler = (Event) throws -> Void 37 | 38 | fileprivate let _source: Observable 39 | fileprivate let _eventHandler: EventHandler 40 | fileprivate let _onSubscribe: (() -> ())? 41 | fileprivate let _onDispose: (() -> ())? 42 | 43 | init(source: Observable, eventHandler: @escaping EventHandler, onSubscribe: (() -> ())?, onDispose: (() -> ())?) { 44 | _source = source 45 | _eventHandler = eventHandler 46 | _onSubscribe = onSubscribe 47 | _onDispose = onDispose 48 | } 49 | 50 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 51 | _onSubscribe?() 52 | let sink = DoSink(parent: self, observer: observer, cancel: cancel) 53 | let subscription = _source.subscribe(sink) 54 | let onDispose = _onDispose 55 | let allSubscriptions = Disposables.create { 56 | subscription.dispose() 57 | onDispose?() 58 | } 59 | return (sink: sink, subscription: allSubscriptions) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Sink.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Sink.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/19/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | class Sink : Disposable { 10 | fileprivate let _observer: O 11 | fileprivate let _cancel: Cancelable 12 | fileprivate var _disposed: Bool 13 | 14 | #if DEBUG 15 | fileprivate var _numberOfConcurrentCalls: AtomicInt = 0 16 | #endif 17 | 18 | init(observer: O, cancel: Cancelable) { 19 | #if TRACE_RESOURCES 20 | let _ = Resources.incrementTotal() 21 | #endif 22 | _observer = observer 23 | _cancel = cancel 24 | _disposed = false 25 | } 26 | 27 | final func forwardOn(_ event: Event) { 28 | #if DEBUG 29 | if AtomicIncrement(&_numberOfConcurrentCalls) > 1 { 30 | rxFatalError("Warning: Recursive call or synchronization error!") 31 | } 32 | 33 | defer { 34 | _ = AtomicDecrement(&_numberOfConcurrentCalls) 35 | } 36 | #endif 37 | if _disposed { 38 | return 39 | } 40 | _observer.on(event) 41 | } 42 | 43 | final func forwarder() -> SinkForward { 44 | return SinkForward(forward: self) 45 | } 46 | 47 | final var disposed: Bool { 48 | return _disposed 49 | } 50 | 51 | func dispose() { 52 | _disposed = true 53 | _cancel.dispose() 54 | } 55 | 56 | deinit { 57 | #if TRACE_RESOURCES 58 | let _ = Resources.decrementTotal() 59 | #endif 60 | } 61 | } 62 | 63 | final class SinkForward: ObserverType { 64 | typealias E = O.E 65 | 66 | private let _forward: Sink 67 | 68 | init(forward: Sink) { 69 | _forward = forward 70 | } 71 | 72 | final func on(_ event: Event) { 73 | switch event { 74 | case .next: 75 | _forward._observer.on(event) 76 | case .error, .completed: 77 | _forward._observer.on(event) 78 | _forward._cancel.dispose() 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SubscribeOn.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubscribeOn.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 6/14/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class SubscribeOnSink : Sink, ObserverType where Ob.E == O.E { 10 | typealias Element = O.E 11 | typealias Parent = SubscribeOn 12 | 13 | let parent: Parent 14 | 15 | init(parent: Parent, observer: O, cancel: Cancelable) { 16 | self.parent = parent 17 | super.init(observer: observer, cancel: cancel) 18 | } 19 | 20 | func on(_ event: Event) { 21 | forwardOn(event) 22 | 23 | if event.isStopEvent { 24 | self.dispose() 25 | } 26 | } 27 | 28 | func run() -> Disposable { 29 | let disposeEverything = SerialDisposable() 30 | let cancelSchedule = SingleAssignmentDisposable() 31 | 32 | disposeEverything.disposable = cancelSchedule 33 | 34 | let disposeSchedule = parent.scheduler.schedule(()) { (_) -> Disposable in 35 | let subscription = self.parent.source.subscribe(self) 36 | disposeEverything.disposable = ScheduledDisposable(scheduler: self.parent.scheduler, disposable: subscription) 37 | return Disposables.create() 38 | } 39 | 40 | cancelSchedule.setDisposable(disposeSchedule) 41 | 42 | return disposeEverything 43 | } 44 | } 45 | 46 | final class SubscribeOn : Producer { 47 | let source: Ob 48 | let scheduler: ImmediateSchedulerType 49 | 50 | init(source: Ob, scheduler: ImmediateSchedulerType) { 51 | self.source = source 52 | self.scheduler = scheduler 53 | } 54 | 55 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Ob.E { 56 | let sink = SubscribeOnSink(parent: self, observer: observer, cancel: cancel) 57 | let subscription = sink.run() 58 | return (sink: sink, subscription: subscription) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/AnonymousDisposable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnonymousDisposable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/15/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents an Action-based disposable. 10 | /// 11 | /// When dispose method is called, disposal action will be dereferenced. 12 | fileprivate final class AnonymousDisposable : DisposeBase, Cancelable { 13 | public typealias DisposeAction = () -> Void 14 | 15 | private var _isDisposed: AtomicInt = 0 16 | private var _disposeAction: DisposeAction? 17 | 18 | /// - returns: Was resource disposed. 19 | public var isDisposed: Bool { 20 | return _isDisposed == 1 21 | } 22 | 23 | /// Constructs a new disposable with the given action used for disposal. 24 | /// 25 | /// - parameter disposeAction: Disposal action which will be run upon calling `dispose`. 26 | fileprivate init(_ disposeAction: @escaping DisposeAction) { 27 | _disposeAction = disposeAction 28 | super.init() 29 | } 30 | 31 | // Non-deprecated version of the constructor, used by `Disposables.create(with:)` 32 | fileprivate init(disposeAction: @escaping DisposeAction) { 33 | _disposeAction = disposeAction 34 | super.init() 35 | } 36 | 37 | /// Calls the disposal action if and only if the current instance hasn't been disposed yet. 38 | /// 39 | /// After invoking disposal action, disposal action will be dereferenced. 40 | fileprivate func dispose() { 41 | if AtomicCompareAndSwap(0, 1, &_isDisposed) { 42 | assert(_isDisposed == 1) 43 | 44 | if let action = _disposeAction { 45 | _disposeAction = nil 46 | action() 47 | } 48 | } 49 | } 50 | } 51 | 52 | extension Disposables { 53 | 54 | /// Constructs a new disposable with the given action used for disposal. 55 | /// 56 | /// - parameter dispose: Disposal action which will be run upon calling `dispose`. 57 | public static func create(with dispose: @escaping () -> ()) -> Cancelable { 58 | return AnonymousDisposable(disposeAction: dispose) 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /smck/Parser/SMLangAST.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HtmlAST.swift 3 | // smck 4 | // 5 | // Created by Daiming on 2017/4/13. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /* 12 | grammer Backus–Naur form(BNF) https://en.wikipedia.org/wiki/Backus-Naur_form 13 | ::= "(" ")" 14 | ::= | , 15 | ::= "def" ";" 16 | ::= "extern" ";" 17 | ::= "+" | "-" | "*" | "/" | "%" 18 | ::= | | | | | "(" ")" 19 | ::= 20 | ::= "(" ")" 21 | ::= "if" "then" "else" 22 | ::= | "," 23 | */ 24 | 25 | struct SMLangPrototype { 26 | let name: String 27 | let params: [String] 28 | } 29 | 30 | indirect enum SMLangExpr { 31 | case number(Double) 32 | case variable(String) 33 | case binary(SMLangExpr, SMLangBinaryOperator, SMLangExpr) 34 | case call(String, [SMLangExpr]) 35 | case ifelse(SMLangExpr, SMLangExpr, SMLangExpr) 36 | } 37 | 38 | struct SMLangDefinition { 39 | let prototype: SMLangPrototype 40 | let expr: SMLangExpr 41 | } 42 | 43 | class SMLangFile { 44 | private(set) var externs = [SMLangPrototype]() 45 | private(set) var definitions = [SMLangDefinition]() 46 | private(set) var expressions = [SMLangExpr]() 47 | private(set) var prototypeMap = [String: SMLangPrototype]() 48 | 49 | func prototype(name:String) -> SMLangPrototype? { 50 | return prototypeMap[name] 51 | } 52 | 53 | func addExpression(_ expression:SMLangExpr) { 54 | expressions.append(expression) 55 | } 56 | 57 | func addExtern(_ prototype:SMLangPrototype) { 58 | externs.append(prototype) 59 | prototypeMap[prototype.name] = prototype 60 | } 61 | 62 | func addDefinition(_ definition:SMLangDefinition) { 63 | definitions.append(definition) 64 | prototypeMap[definition.prototype.name] = definition.prototype 65 | } 66 | 67 | } 68 | 69 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Scan.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Scan.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 6/14/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class ScanSink : Sink, ObserverType { 10 | typealias Accumulate = O.E 11 | typealias Parent = Scan 12 | typealias E = ElementType 13 | 14 | fileprivate let _parent: Parent 15 | fileprivate var _accumulate: Accumulate 16 | 17 | init(parent: Parent, observer: O, cancel: Cancelable) { 18 | _parent = parent 19 | _accumulate = parent._seed 20 | super.init(observer: observer, cancel: cancel) 21 | } 22 | 23 | func on(_ event: Event) { 24 | switch event { 25 | case .next(let element): 26 | do { 27 | _accumulate = try _parent._accumulator(_accumulate, element) 28 | forwardOn(.next(_accumulate)) 29 | } 30 | catch let error { 31 | forwardOn(.error(error)) 32 | dispose() 33 | } 34 | case .error(let error): 35 | forwardOn(.error(error)) 36 | dispose() 37 | case .completed: 38 | forwardOn(.completed) 39 | dispose() 40 | } 41 | } 42 | 43 | } 44 | 45 | final class Scan: Producer { 46 | typealias Accumulator = (Accumulate, Element) throws -> Accumulate 47 | 48 | fileprivate let _source: Observable 49 | fileprivate let _seed: Accumulate 50 | fileprivate let _accumulator: Accumulator 51 | 52 | init(source: Observable, seed: Accumulate, accumulator: @escaping Accumulator) { 53 | _source = source 54 | _seed = seed 55 | _accumulator = accumulator 56 | } 57 | 58 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Accumulate { 59 | let sink = ScanSink(parent: self, observer: observer, cancel: cancel) 60 | let subscription = _source.subscribe(sink) 61 | return (sink: sink, subscription: subscription) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/AnonymousObservable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnonymousObservable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/8/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class AnonymousObservableSink : Sink, ObserverType { 10 | typealias E = O.E 11 | typealias Parent = AnonymousObservable 12 | 13 | // state 14 | private var _isStopped: AtomicInt = 0 15 | 16 | #if DEBUG 17 | fileprivate var _numberOfConcurrentCalls: AtomicInt = 0 18 | #endif 19 | 20 | override init(observer: O, cancel: Cancelable) { 21 | super.init(observer: observer, cancel: cancel) 22 | } 23 | 24 | func on(_ event: Event) { 25 | #if DEBUG 26 | if AtomicIncrement(&_numberOfConcurrentCalls) > 1 { 27 | rxFatalError("Warning: Recursive call or synchronization error!") 28 | } 29 | 30 | defer { 31 | _ = AtomicDecrement(&_numberOfConcurrentCalls) 32 | } 33 | #endif 34 | switch event { 35 | case .next: 36 | if _isStopped == 1 { 37 | return 38 | } 39 | forwardOn(event) 40 | case .error, .completed: 41 | if AtomicCompareAndSwap(0, 1, &_isStopped) { 42 | forwardOn(event) 43 | dispose() 44 | } 45 | } 46 | } 47 | 48 | func run(_ parent: Parent) -> Disposable { 49 | return parent._subscribeHandler(AnyObserver(self)) 50 | } 51 | } 52 | 53 | final class AnonymousObservable : Producer { 54 | typealias SubscribeHandler = (AnyObserver) -> Disposable 55 | 56 | let _subscribeHandler: SubscribeHandler 57 | 58 | init(_ subscribeHandler: @escaping SubscribeHandler) { 59 | _subscribeHandler = subscribeHandler 60 | } 61 | 62 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 63 | let sink = AnonymousObservableSink(observer: observer, cancel: cancel) 64 | let subscription = sink.run(self) 65 | return (sink: sink, subscription: subscription) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /smck/Console/Console.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ConsoleIO.swift 3 | // SMCheckProjectCL 4 | // 5 | // Created by daiming on 2017/3/6. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum OutputType { 12 | case error 13 | case standard 14 | case description 15 | } 16 | 17 | enum OptionType: String { 18 | case seekFile = "s" //列出文件夹下的所有文件 19 | case unUseMethods = "m" //列出文件夹下没有用到的函数 20 | case unUseObject = "o" //列出无用类 21 | case h5ToSwift = "h2s" //将h5转swift 22 | case help = "h" //查看帮助 23 | case quit = "q" //退出互动操作 24 | case unknown 25 | 26 | init(value: String) { 27 | switch value { 28 | case "s": 29 | self = .seekFile 30 | case "m": 31 | self = .unUseMethods 32 | case "o": 33 | self = .unUseObject 34 | case "h2s": 35 | self = .h5ToSwift 36 | case "h": 37 | self = .help 38 | case "q": 39 | self = .quit 40 | default: 41 | self = .unknown 42 | } 43 | } 44 | } 45 | 46 | class Console { 47 | class func printUsage() { 48 | let exName = (CommandLine.arguments[0] as NSString).lastPathComponent 49 | 50 | print("Usage:") 51 | print("\(exName) -f filePath like /") 52 | print("\(exName) -h more infomation") 53 | } 54 | 55 | class func getInput() -> String { 56 | let keyboard = FileHandle.standardInput 57 | let inputData = keyboard.availableData 58 | let strData = String(data:inputData, encoding:String.Encoding.utf8)! 59 | return strData.trimmingCharacters(in: CharacterSet.newlines) 60 | } 61 | 62 | class func outPrint(_ message: String, to: OutputType = .standard) { 63 | switch to { 64 | case .standard: 65 | print("\(message)") 66 | case .description: 67 | print("😈 \(message)") 68 | case .error: 69 | print("😱 \(message)\n", stderr) 70 | } 71 | } 72 | 73 | class func getOption(_ option: String) -> (option:OptionType, value:String) { 74 | return (OptionType(value:option),option) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Variable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Variable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/28/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Variable is a wrapper for `BehaviorSubject`. 10 | /// 11 | /// Unlike `BehaviorSubject` it can't terminate with error, and when variable is deallocated 12 | /// it will complete it's observable sequence (`asObservable`). 13 | public final class Variable { 14 | 15 | public typealias E = Element 16 | 17 | private let _subject: BehaviorSubject 18 | 19 | private var _lock = SpinLock() 20 | 21 | // state 22 | private var _value: E 23 | 24 | #if DEBUG 25 | fileprivate var _numberOfConcurrentCalls: AtomicInt = 0 26 | #endif 27 | 28 | /// Gets or sets current value of variable. 29 | /// 30 | /// Whenever a new value is set, all the observers are notified of the change. 31 | /// 32 | /// Even if the newly set value is same as the old value, observers are still notified for change. 33 | public var value: E { 34 | get { 35 | _lock.lock(); defer { _lock.unlock() } 36 | return _value 37 | } 38 | set(newValue) { 39 | #if DEBUG 40 | if AtomicIncrement(&_numberOfConcurrentCalls) > 1 { 41 | rxFatalError("Warning: Recursive call or synchronization error!") 42 | } 43 | 44 | defer { 45 | _ = AtomicDecrement(&_numberOfConcurrentCalls) 46 | } 47 | #endif 48 | _lock.lock() 49 | _value = newValue 50 | _lock.unlock() 51 | 52 | _subject.on(.next(newValue)) 53 | } 54 | } 55 | 56 | /// Initializes variable with initial value. 57 | /// 58 | /// - parameter value: Initial variable value. 59 | public init(_ value: Element) { 60 | _value = value 61 | _subject = BehaviorSubject(value: value) 62 | } 63 | 64 | /// - returns: Canonical interface for push style sequence 65 | public func asObservable() -> Observable { 66 | return _subject 67 | } 68 | 69 | deinit { 70 | _subject.on(.completed) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /smck/Parser/CSSLexer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CSSLexer.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/4/19. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class CSSLexer { 12 | let input: String 13 | var index: String.Index 14 | 15 | init(input:String) { 16 | var newStr = "" 17 | let annotationBlockPattern = "/\\*[\\s\\S]*?\\*/" //匹配/*...*/这样的注释 18 | let regexBlock = try! NSRegularExpression(pattern: annotationBlockPattern, options: NSRegularExpression.Options(rawValue:0)) 19 | newStr = regexBlock.stringByReplacingMatches(in: input, options: NSRegularExpression.MatchingOptions(rawValue:0), range: NSMakeRange(0, input.characters.count), withTemplate: Sb.space) 20 | self.input = newStr 21 | self.index = newStr.startIndex 22 | } 23 | 24 | public func lex() -> [String] { 25 | var tks = [String]() 26 | while let tk = advanceToNextToken() { 27 | if tk == CSSSb.space || tk == CSSSb.empty { 28 | } else { 29 | tks.append(tk) 30 | } 31 | } 32 | return tks 33 | } 34 | 35 | func advanceToNextToken() -> String? { 36 | //检测尾 37 | guard currentChar != nil else { 38 | return nil 39 | } 40 | let keyMap = [CSSSb.braceL, CSSSb.braceR, CSSSb.pSign, CSSSb.dot, CSSSb.semicolon, CSSSb.colon, CSSSb.rBktL, CSSSb.rBktR, CSSSb.space] 41 | let currentStr = currentChar?.description 42 | var str = "" 43 | if keyMap.contains(currentStr!) { 44 | advanceIndex() 45 | return currentStr 46 | } else { 47 | while let charStr = currentChar?.description, !keyMap.contains(charStr) { 48 | str.append(charStr) 49 | advanceIndex() 50 | } 51 | return str 52 | } 53 | 54 | 55 | } 56 | 57 | /*---------------*/ 58 | var currentChar: Character? { 59 | return index < input.endIndex ? input[index] : nil 60 | } 61 | func advanceIndex() { 62 | input.characters.formIndex(after: &index) 63 | } 64 | func advanceSpace() { 65 | while let char = currentChar, char.isSpace { 66 | advanceIndex() 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Observable+Concurrency.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Observable+Concurrency.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/15/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | // MARK: observeOn 10 | 11 | extension ObservableType { 12 | 13 | /** 14 | Wraps the source sequence in order to run its observer callbacks on the specified scheduler. 15 | 16 | This only invokes observer callbacks on a `scheduler`. In case the subscription and/or unsubscription 17 | actions have side-effects that require to be run on a scheduler, use `subscribeOn`. 18 | 19 | - seealso: [observeOn operator on reactivex.io](http://reactivex.io/documentation/operators/observeon.html) 20 | 21 | - parameter scheduler: Scheduler to notify observers on. 22 | - returns: The source sequence whose observations happen on the specified scheduler. 23 | */ 24 | public func observeOn(_ scheduler: ImmediateSchedulerType) 25 | -> Observable { 26 | if let scheduler = scheduler as? SerialDispatchQueueScheduler { 27 | return ObserveOnSerialDispatchQueue(source: self.asObservable(), scheduler: scheduler) 28 | } 29 | else { 30 | return ObserveOn(source: self.asObservable(), scheduler: scheduler) 31 | } 32 | } 33 | } 34 | 35 | // MARK: subscribeOn 36 | 37 | extension ObservableType { 38 | 39 | /** 40 | Wraps the source sequence in order to run its subscription and unsubscription logic on the specified 41 | scheduler. 42 | 43 | This operation is not commonly used. 44 | 45 | This only performs the side-effects of subscription and unsubscription on the specified scheduler. 46 | 47 | In order to invoke observer callbacks on a `scheduler`, use `observeOn`. 48 | 49 | - seealso: [subscribeOn operator on reactivex.io](http://reactivex.io/documentation/operators/subscribeon.html) 50 | 51 | - parameter scheduler: Scheduler to perform subscription and unsubscription actions on. 52 | - returns: The source sequence whose subscriptions and unsubscriptions happen on the specified scheduler. 53 | */ 54 | public func subscribeOn(_ scheduler: ImmediateSchedulerType) 55 | -> Observable { 56 | return SubscribeOn(source: self, scheduler: scheduler) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Event.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Event.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/8/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents a sequence event. 10 | /// 11 | /// Sequence grammar: 12 | /// **next\* (error | completed)** 13 | public enum Event { 14 | /// Next element is produced. 15 | case next(Element) 16 | 17 | /// Sequence terminated with an error. 18 | case error(Swift.Error) 19 | 20 | /// Sequence completed successfully. 21 | case completed 22 | } 23 | 24 | extension Event : CustomDebugStringConvertible { 25 | /// - returns: Description of event. 26 | public var debugDescription: String { 27 | switch self { 28 | case .next(let value): 29 | return "next(\(value))" 30 | case .error(let error): 31 | return "error(\(error))" 32 | case .completed: 33 | return "completed" 34 | } 35 | } 36 | } 37 | 38 | extension Event { 39 | /// Is `Completed` or `Error` event. 40 | public var isStopEvent: Bool { 41 | switch self { 42 | case .next: return false 43 | case .error, .completed: return true 44 | } 45 | } 46 | 47 | /// If `Next` event, returns element value. 48 | public var element: Element? { 49 | if case .next(let value) = self { 50 | return value 51 | } 52 | return nil 53 | } 54 | 55 | /// If `Error` event, returns error. 56 | public var error: Swift.Error? { 57 | if case .error(let error) = self { 58 | return error 59 | } 60 | return nil 61 | } 62 | } 63 | 64 | extension Event { 65 | /// Maps sequence elements using transform. If error happens during the transform .error 66 | /// will be returned as value 67 | public func map(_ transform: (Element) throws -> Result) -> Event { 68 | do { 69 | switch self { 70 | case let .next(element): 71 | return .next(try transform(element)) 72 | case let .error(error): 73 | return .error(error) 74 | case .completed: 75 | return .completed 76 | } 77 | } 78 | catch let e { 79 | return .error(e) 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Optional.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Optional.swift 3 | // RxSwift 4 | // 5 | // Created by tarunon on 2016/12/13. 6 | // Copyright © 2016 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class ObservableOptionalScheduledSink : Sink { 10 | typealias E = O.E 11 | typealias Parent = ObservableOptionalScheduled 12 | 13 | private let _parent: Parent 14 | 15 | init(parent: Parent, observer: O, cancel: Cancelable) { 16 | _parent = parent 17 | super.init(observer: observer, cancel: cancel) 18 | } 19 | 20 | func run() -> Disposable { 21 | return _parent._scheduler.schedule(_parent._optional) { (optional: E?) -> Disposable in 22 | if let next = optional { 23 | self.forwardOn(.next(next)) 24 | return self._parent._scheduler.schedule(()) { _ in 25 | self.forwardOn(.completed) 26 | self.dispose() 27 | return Disposables.create() 28 | } 29 | } else { 30 | self.forwardOn(.completed) 31 | self.dispose() 32 | return Disposables.create() 33 | } 34 | } 35 | } 36 | } 37 | 38 | final class ObservableOptionalScheduled : Producer { 39 | fileprivate let _optional: E? 40 | fileprivate let _scheduler: ImmediateSchedulerType 41 | 42 | init(optional: E?, scheduler: ImmediateSchedulerType) { 43 | _optional = optional 44 | _scheduler = scheduler 45 | } 46 | 47 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == E { 48 | let sink = ObservableOptionalScheduledSink(parent: self, observer: observer, cancel: cancel) 49 | let subscription = sink.run() 50 | return (sink: sink, subscription: subscription) 51 | } 52 | } 53 | 54 | final class ObservableOptional: Producer { 55 | private let _optional: E? 56 | 57 | init(optional: E?) { 58 | _optional = optional 59 | } 60 | 61 | override func subscribe(_ observer: O) -> Disposable where O.E == E { 62 | if let element = _optional { 63 | observer.on(.next(element)) 64 | } 65 | observer.on(.completed) 66 | return Disposables.create() 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ElementAt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ElementAt.swift 3 | // RxSwift 4 | // 5 | // Created by Junior B. on 21/10/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | 10 | final class ElementAtSink : Sink, ObserverType { 11 | typealias SourceType = O.E 12 | typealias Parent = ElementAt 13 | 14 | let _parent: Parent 15 | var _i: Int 16 | 17 | init(parent: Parent, observer: O, cancel: Cancelable) { 18 | _parent = parent 19 | _i = parent._index 20 | 21 | super.init(observer: observer, cancel: cancel) 22 | } 23 | 24 | func on(_ event: Event) { 25 | switch event { 26 | case .next(_): 27 | 28 | if (_i == 0) { 29 | forwardOn(event) 30 | forwardOn(.completed) 31 | self.dispose() 32 | } 33 | 34 | do { 35 | let _ = try decrementChecked(&_i) 36 | } catch(let e) { 37 | forwardOn(.error(e)) 38 | dispose() 39 | return 40 | } 41 | 42 | case .error(let e): 43 | forwardOn(.error(e)) 44 | self.dispose() 45 | case .completed: 46 | if (_parent._throwOnEmpty) { 47 | forwardOn(.error(RxError.argumentOutOfRange)) 48 | } else { 49 | forwardOn(.completed) 50 | } 51 | 52 | self.dispose() 53 | } 54 | } 55 | } 56 | 57 | final class ElementAt : Producer { 58 | 59 | let _source: Observable 60 | let _throwOnEmpty: Bool 61 | let _index: Int 62 | 63 | init(source: Observable, index: Int, throwOnEmpty: Bool) { 64 | if index < 0 { 65 | rxFatalError("index can't be negative") 66 | } 67 | 68 | self._source = source 69 | self._index = index 70 | self._throwOnEmpty = throwOnEmpty 71 | } 72 | 73 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == SourceType { 74 | let sink = ElementAtSink(parent: self, observer: observer, cancel: cancel) 75 | let subscription = _source.subscribe(sink) 76 | return (sink: sink, subscription: subscription) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Platform.Darwin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Platform.Darwin.swift 3 | // Platform 4 | // 5 | // Created by Krunoslav Zaher on 12/29/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) 10 | 11 | import Darwin 12 | import class Foundation.Thread 13 | import func Foundation.OSAtomicCompareAndSwap32Barrier 14 | import func Foundation.OSAtomicIncrement32Barrier 15 | import func Foundation.OSAtomicDecrement32Barrier 16 | import protocol Foundation.NSCopying 17 | 18 | typealias AtomicInt = Int32 19 | 20 | fileprivate func castToUInt32Pointer(_ pointer: UnsafeMutablePointer) -> UnsafeMutablePointer { 21 | let raw = UnsafeMutableRawPointer(pointer) 22 | return raw.assumingMemoryBound(to: UInt32.self) 23 | } 24 | 25 | let AtomicCompareAndSwap = OSAtomicCompareAndSwap32Barrier 26 | let AtomicIncrement = OSAtomicIncrement32Barrier 27 | let AtomicDecrement = OSAtomicDecrement32Barrier 28 | func AtomicOr(_ mask: UInt32, _ theValue : UnsafeMutablePointer) -> Int32 { 29 | return OSAtomicOr32OrigBarrier(mask, castToUInt32Pointer(theValue)) 30 | } 31 | func AtomicFlagSet(_ mask: UInt32, _ theValue : UnsafeMutablePointer) -> Bool { 32 | // just used to create a barrier 33 | OSAtomicXor32OrigBarrier(0, castToUInt32Pointer(theValue)) 34 | return (theValue.pointee & Int32(mask)) != 0 35 | } 36 | 37 | extension Thread { 38 | 39 | static func setThreadLocalStorageValue(_ value: T?, forKey key: NSCopying 40 | ) { 41 | let currentThread = Thread.current 42 | let threadDictionary = currentThread.threadDictionary 43 | 44 | if let newValue = value { 45 | threadDictionary[key] = newValue 46 | } 47 | else { 48 | threadDictionary[key] = nil 49 | } 50 | 51 | } 52 | static func getThreadLocalStorageValueForKey(_ key: NSCopying) -> T? { 53 | let currentThread = Thread.current 54 | let threadDictionary = currentThread.threadDictionary 55 | 56 | return threadDictionary[key] as? T 57 | } 58 | } 59 | 60 | extension AtomicInt { 61 | func valueSnapshot() -> Int32 { 62 | return self 63 | } 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/AnyObserver.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnyObserver.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/28/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// A type-erased `ObserverType`. 10 | /// 11 | /// Forwards operations to an arbitrary underlying observer with the same `Element` type, hiding the specifics of the underlying observer type. 12 | public struct AnyObserver : ObserverType { 13 | /// The type of elements in sequence that observer can observe. 14 | public typealias E = Element 15 | 16 | /// Anonymous event handler type. 17 | public typealias EventHandler = (Event) -> Void 18 | 19 | private let observer: EventHandler 20 | 21 | /// Construct an instance whose `on(event)` calls `eventHandler(event)` 22 | /// 23 | /// - parameter eventHandler: Event handler that observes sequences events. 24 | public init(eventHandler: @escaping EventHandler) { 25 | self.observer = eventHandler 26 | } 27 | 28 | /// Construct an instance whose `on(event)` calls `observer.on(event)` 29 | /// 30 | /// - parameter observer: Observer that receives sequence events. 31 | public init(_ observer: O) where O.E == Element { 32 | self.observer = observer.on 33 | } 34 | 35 | /// Send `event` to this observer. 36 | /// 37 | /// - parameter event: Event instance. 38 | public func on(_ event: Event) { 39 | return self.observer(event) 40 | } 41 | 42 | /// Erases type of observer and returns canonical observer. 43 | /// 44 | /// - returns: type erased observer. 45 | public func asObserver() -> AnyObserver { 46 | return self 47 | } 48 | } 49 | 50 | extension ObserverType { 51 | /// Erases type of observer and returns canonical observer. 52 | /// 53 | /// - returns: type erased observer. 54 | public func asObserver() -> AnyObserver { 55 | return AnyObserver(self) 56 | } 57 | 58 | /// Transforms observer of type R to type E using custom transform method. 59 | /// Each event sent to result observer is transformed and sent to `self`. 60 | /// 61 | /// - returns: observer that transforms events. 62 | public func mapObserver(_ transform: @escaping (R) throws -> E) -> AnyObserver { 63 | return AnyObserver { e in 64 | self.on(e.map(transform)) 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/DistinctUntilChanged.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DistinctUntilChanged.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/15/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class DistinctUntilChangedSink: Sink, ObserverType { 10 | typealias E = O.E 11 | 12 | private let _parent: DistinctUntilChanged 13 | private var _currentKey: Key? = nil 14 | 15 | init(parent: DistinctUntilChanged, observer: O, cancel: Cancelable) { 16 | _parent = parent 17 | super.init(observer: observer, cancel: cancel) 18 | } 19 | 20 | func on(_ event: Event) { 21 | switch event { 22 | case .next(let value): 23 | do { 24 | let key = try _parent._selector(value) 25 | var areEqual = false 26 | if let currentKey = _currentKey { 27 | areEqual = try _parent._comparer(currentKey, key) 28 | } 29 | 30 | if areEqual { 31 | return 32 | } 33 | 34 | _currentKey = key 35 | 36 | forwardOn(event) 37 | } 38 | catch let error { 39 | forwardOn(.error(error)) 40 | dispose() 41 | } 42 | case .error, .completed: 43 | forwardOn(event) 44 | dispose() 45 | } 46 | } 47 | } 48 | 49 | final class DistinctUntilChanged: Producer { 50 | typealias KeySelector = (Element) throws -> Key 51 | typealias EqualityComparer = (Key, Key) throws -> Bool 52 | 53 | fileprivate let _source: Observable 54 | fileprivate let _selector: KeySelector 55 | fileprivate let _comparer: EqualityComparer 56 | 57 | init(source: Observable, selector: @escaping KeySelector, comparer: @escaping EqualityComparer) { 58 | _source = source 59 | _selector = selector 60 | _comparer = comparer 61 | } 62 | 63 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 64 | let sink = DistinctUntilChangedSink(parent: self, observer: observer, cancel: cancel) 65 | let subscription = _source.subscribe(sink) 66 | return (sink: sink, subscription: subscription) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SerialDisposable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SerialDisposable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/12/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Represents a disposable resource whose underlying disposable resource can be replaced by another disposable resource, causing automatic disposal of the previous underlying disposable resource. 10 | public final class SerialDisposable : DisposeBase, Cancelable { 11 | private var _lock = SpinLock() 12 | 13 | // state 14 | private var _current = nil as Disposable? 15 | private var _isDisposed = false 16 | 17 | /// - returns: Was resource disposed. 18 | public var isDisposed: Bool { 19 | return _isDisposed 20 | } 21 | 22 | /// Initializes a new instance of the `SerialDisposable`. 23 | override public init() { 24 | super.init() 25 | } 26 | 27 | /** 28 | Gets or sets the underlying disposable. 29 | 30 | Assigning this property disposes the previous disposable object. 31 | 32 | If the `SerialDisposable` has already been disposed, assignment to this property causes immediate disposal of the given disposable object. 33 | */ 34 | public var disposable: Disposable { 35 | get { 36 | return _lock.calculateLocked { 37 | return self.disposable 38 | } 39 | } 40 | set (newDisposable) { 41 | let disposable: Disposable? = _lock.calculateLocked { 42 | if _isDisposed { 43 | return newDisposable 44 | } 45 | else { 46 | let toDispose = _current 47 | _current = newDisposable 48 | return toDispose 49 | } 50 | } 51 | 52 | if let disposable = disposable { 53 | disposable.dispose() 54 | } 55 | } 56 | } 57 | 58 | /// Disposes the underlying disposable as well as all future replacements. 59 | public func dispose() { 60 | _dispose()?.dispose() 61 | } 62 | 63 | private func _dispose() -> Disposable? { 64 | _lock.lock(); defer { _lock.unlock() } 65 | if _isDisposed { 66 | return nil 67 | } 68 | else { 69 | _isDisposed = true 70 | let current = _current 71 | _current = nil 72 | return current 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SchedulerServices+Emulation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SchedulerServices+Emulation.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 6/6/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | enum SchedulePeriodicRecursiveCommand { 10 | case tick 11 | case dispatchStart 12 | } 13 | 14 | final class SchedulePeriodicRecursive { 15 | typealias RecursiveAction = (State) -> State 16 | typealias RecursiveScheduler = AnyRecursiveScheduler 17 | 18 | private let _scheduler: SchedulerType 19 | private let _startAfter: RxTimeInterval 20 | private let _period: RxTimeInterval 21 | private let _action: RecursiveAction 22 | 23 | private var _state: State 24 | private var _pendingTickCount: AtomicInt = 0 25 | 26 | init(scheduler: SchedulerType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping RecursiveAction, state: State) { 27 | _scheduler = scheduler 28 | _startAfter = startAfter 29 | _period = period 30 | _action = action 31 | _state = state 32 | } 33 | 34 | func start() -> Disposable { 35 | return _scheduler.scheduleRecursive(SchedulePeriodicRecursiveCommand.tick, dueTime: _startAfter, action: self.tick) 36 | } 37 | 38 | func tick(_ command: SchedulePeriodicRecursiveCommand, scheduler: RecursiveScheduler) -> Void { 39 | // Tries to emulate periodic scheduling as best as possible. 40 | // The problem that could arise is if handling periodic ticks take too long, or 41 | // tick interval is short. 42 | switch command { 43 | case .tick: 44 | scheduler.schedule(.tick, dueTime: _period) 45 | 46 | // The idea is that if on tick there wasn't any item enqueued, schedule to perform work immediatelly. 47 | // Else work will be scheduled after previous enqueued work completes. 48 | if AtomicIncrement(&_pendingTickCount) == 1 { 49 | self.tick(.dispatchStart, scheduler: scheduler) 50 | } 51 | 52 | case .dispatchStart: 53 | _state = _action(_state) 54 | // Start work and schedule check is this last batch of work 55 | if AtomicDecrement(&_pendingTickCount) > 0 { 56 | // This gives priority to scheduler emulation, it's not perfect, but helps 57 | scheduler.schedule(SchedulePeriodicRecursiveCommand.dispatchStart) 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SingleAsync.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SingleAsync.swift 3 | // RxSwift 4 | // 5 | // Created by Junior B. on 09/11/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class SingleAsyncSink : Sink, ObserverType { 10 | typealias ElementType = O.E 11 | typealias Parent = SingleAsync 12 | typealias E = ElementType 13 | 14 | private let _parent: Parent 15 | private var _seenValue: Bool = false 16 | 17 | init(parent: Parent, observer: O, cancel: Cancelable) { 18 | _parent = parent 19 | super.init(observer: observer, cancel: cancel) 20 | } 21 | 22 | func on(_ event: Event) { 23 | switch event { 24 | case .next(let value): 25 | do { 26 | let forward = try _parent._predicate?(value) ?? true 27 | if !forward { 28 | return 29 | } 30 | } 31 | catch let error { 32 | forwardOn(.error(error as Swift.Error)) 33 | dispose() 34 | return 35 | } 36 | 37 | if _seenValue == false { 38 | _seenValue = true 39 | forwardOn(.next(value)) 40 | } else { 41 | forwardOn(.error(RxError.moreThanOneElement)) 42 | dispose() 43 | } 44 | 45 | case .error: 46 | forwardOn(event) 47 | dispose() 48 | case .completed: 49 | if (!_seenValue) { 50 | forwardOn(.error(RxError.noElements)) 51 | } else { 52 | forwardOn(.completed) 53 | } 54 | dispose() 55 | } 56 | } 57 | } 58 | 59 | final class SingleAsync: Producer { 60 | typealias Predicate = (Element) throws -> Bool 61 | 62 | fileprivate let _source: Observable 63 | fileprivate let _predicate: Predicate? 64 | 65 | init(source: Observable, predicate: Predicate? = nil) { 66 | _source = source 67 | _predicate = predicate 68 | } 69 | 70 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 71 | let sink = SingleAsyncSink(parent: self, observer: observer, cancel: cancel) 72 | let subscription = _source.subscribe(sink) 73 | return (sink: sink, subscription: subscription) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Timer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Timer.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 6/7/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class TimerSink : Sink where O.E : SignedInteger { 10 | typealias Parent = Timer 11 | 12 | private let _parent: Parent 13 | 14 | init(parent: Parent, observer: O, cancel: Cancelable) { 15 | _parent = parent 16 | super.init(observer: observer, cancel: cancel) 17 | } 18 | 19 | func run() -> Disposable { 20 | return _parent._scheduler.schedulePeriodic(0 as O.E, startAfter: _parent._dueTime, period: _parent._period!) { state in 21 | self.forwardOn(.next(state)) 22 | return state &+ 1 23 | } 24 | } 25 | } 26 | 27 | final class TimerOneOffSink : Sink where O.E : SignedInteger { 28 | typealias Parent = Timer 29 | 30 | private let _parent: Parent 31 | 32 | init(parent: Parent, observer: O, cancel: Cancelable) { 33 | _parent = parent 34 | super.init(observer: observer, cancel: cancel) 35 | } 36 | 37 | func run() -> Disposable { 38 | return _parent._scheduler.scheduleRelative(self, dueTime: _parent._dueTime) { (`self`) -> Disposable in 39 | self.forwardOn(.next(0)) 40 | self.forwardOn(.completed) 41 | self.dispose() 42 | 43 | return Disposables.create() 44 | } 45 | } 46 | } 47 | 48 | final class Timer: Producer { 49 | fileprivate let _scheduler: SchedulerType 50 | fileprivate let _dueTime: RxTimeInterval 51 | fileprivate let _period: RxTimeInterval? 52 | 53 | init(dueTime: RxTimeInterval, period: RxTimeInterval?, scheduler: SchedulerType) { 54 | _scheduler = scheduler 55 | _dueTime = dueTime 56 | _period = period 57 | } 58 | 59 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == E { 60 | if let _ = _period { 61 | let sink = TimerSink(parent: self, observer: observer, cancel: cancel) 62 | let subscription = sink.run() 63 | return (sink: sink, subscription: subscription) 64 | } 65 | else { 66 | let sink = TimerOneOffSink(parent: self, observer: observer, cancel: cancel) 67 | let subscription = sink.run() 68 | return (sink: sink, subscription: subscription) 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Multicast.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Multicast.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/27/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class MulticastSink: Sink, ObserverType { 10 | typealias Element = O.E 11 | typealias ResultType = Element 12 | typealias MutlicastType = Multicast 13 | 14 | private let _parent: MutlicastType 15 | 16 | init(parent: MutlicastType, observer: O, cancel: Cancelable) { 17 | _parent = parent 18 | super.init(observer: observer, cancel: cancel) 19 | } 20 | 21 | func run() -> Disposable { 22 | do { 23 | let subject = try _parent._subjectSelector() 24 | let connectable = ConnectableObservableAdapter(source: _parent._source, subject: subject) 25 | 26 | let observable = try _parent._selector(connectable) 27 | 28 | let subscription = observable.subscribe(self) 29 | let connection = connectable.connect() 30 | 31 | return Disposables.create(subscription, connection) 32 | } 33 | catch let e { 34 | forwardOn(.error(e)) 35 | dispose() 36 | return Disposables.create() 37 | } 38 | } 39 | 40 | func on(_ event: Event) { 41 | forwardOn(event) 42 | switch event { 43 | case .next: break 44 | case .error, .completed: 45 | dispose() 46 | } 47 | } 48 | } 49 | 50 | final class Multicast: Producer { 51 | typealias SubjectSelectorType = () throws -> S 52 | typealias SelectorType = (Observable) throws -> Observable 53 | 54 | fileprivate let _source: Observable 55 | fileprivate let _subjectSelector: SubjectSelectorType 56 | fileprivate let _selector: SelectorType 57 | 58 | init(source: Observable, subjectSelector: @escaping SubjectSelectorType, selector: @escaping SelectorType) { 59 | _source = source 60 | _subjectSelector = subjectSelector 61 | _selector = selector 62 | } 63 | 64 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == R { 65 | let sink = MulticastSink(parent: self, observer: observer, cancel: cancel) 66 | let subscription = sink.run() 67 | return (sink: sink, subscription: subscription) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Generate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generate.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 9/2/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class GenerateSink : Sink { 10 | typealias Parent = Generate 11 | 12 | private let _parent: Parent 13 | 14 | private var _state: S 15 | 16 | init(parent: Parent, observer: O, cancel: Cancelable) { 17 | _parent = parent 18 | _state = parent._initialState 19 | super.init(observer: observer, cancel: cancel) 20 | } 21 | 22 | func run() -> Disposable { 23 | return _parent._scheduler.scheduleRecursive(true) { (isFirst, recurse) -> Void in 24 | do { 25 | if !isFirst { 26 | self._state = try self._parent._iterate(self._state) 27 | } 28 | 29 | if try self._parent._condition(self._state) { 30 | let result = try self._parent._resultSelector(self._state) 31 | self.forwardOn(.next(result)) 32 | 33 | recurse(false) 34 | } 35 | else { 36 | self.forwardOn(.completed) 37 | self.dispose() 38 | } 39 | } 40 | catch let error { 41 | self.forwardOn(.error(error)) 42 | self.dispose() 43 | } 44 | } 45 | } 46 | } 47 | 48 | final class Generate : Producer { 49 | fileprivate let _initialState: S 50 | fileprivate let _condition: (S) throws -> Bool 51 | fileprivate let _iterate: (S) throws -> S 52 | fileprivate let _resultSelector: (S) throws -> E 53 | fileprivate let _scheduler: ImmediateSchedulerType 54 | 55 | init(initialState: S, condition: @escaping (S) throws -> Bool, iterate: @escaping (S) throws -> S, resultSelector: @escaping (S) throws -> E, scheduler: ImmediateSchedulerType) { 56 | _initialState = initialState 57 | _condition = condition 58 | _iterate = iterate 59 | _resultSelector = resultSelector 60 | _scheduler = scheduler 61 | super.init() 62 | } 63 | 64 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == E { 65 | let sink = GenerateSink(parent: self, observer: observer, cancel: cancel) 66 | let subscription = sink.run() 67 | return (sink: sink, subscription: subscription) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Using.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Using.swift 3 | // RxSwift 4 | // 5 | // Created by Yury Korolev on 10/15/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class UsingSink : Sink, ObserverType { 10 | typealias SourceType = O.E 11 | typealias Parent = Using 12 | 13 | private let _parent: Parent 14 | 15 | init(parent: Parent, observer: O, cancel: Cancelable) { 16 | _parent = parent 17 | super.init(observer: observer, cancel: cancel) 18 | } 19 | 20 | func run() -> Disposable { 21 | var disposable = Disposables.create() 22 | 23 | do { 24 | let resource = try _parent._resourceFactory() 25 | disposable = resource 26 | let source = try _parent._observableFactory(resource) 27 | 28 | return Disposables.create( 29 | source.subscribe(self), 30 | disposable 31 | ) 32 | } catch let error { 33 | return Disposables.create( 34 | Observable.error(error).subscribe(self), 35 | disposable 36 | ) 37 | } 38 | } 39 | 40 | func on(_ event: Event) { 41 | switch event { 42 | case let .next(value): 43 | forwardOn(.next(value)) 44 | case let .error(error): 45 | forwardOn(.error(error)) 46 | dispose() 47 | case .completed: 48 | forwardOn(.completed) 49 | dispose() 50 | } 51 | } 52 | } 53 | 54 | class Using: Producer { 55 | 56 | typealias E = SourceType 57 | 58 | typealias ResourceFactory = () throws -> ResourceType 59 | typealias ObservableFactory = (ResourceType) throws -> Observable 60 | 61 | fileprivate let _resourceFactory: ResourceFactory 62 | fileprivate let _observableFactory: ObservableFactory 63 | 64 | 65 | init(resourceFactory: @escaping ResourceFactory, observableFactory: @escaping ObservableFactory) { 66 | _resourceFactory = resourceFactory 67 | _observableFactory = observableFactory 68 | } 69 | 70 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == E { 71 | let sink = UsingSink(parent: self, observer: observer, cancel: cancel) 72 | let subscription = sink.run() 73 | return (sink: sink, subscription: subscription) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/MainScheduler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainScheduler.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/8/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | import Dispatch 10 | 11 | /** 12 | Abstracts work that needs to be performed on `DispatchQueue.main`. In case `schedule` methods are called from `DispatchQueue.main`, it will perform action immediately without scheduling. 13 | 14 | This scheduler is usually used to perform UI work. 15 | 16 | Main scheduler is a specialization of `SerialDispatchQueueScheduler`. 17 | 18 | This scheduler is optimized for `observeOn` operator. To ensure observable sequence is subscribed on main thread using `subscribeOn` 19 | operator please use `ConcurrentMainScheduler` because it is more optimized for that purpose. 20 | */ 21 | public final class MainScheduler : SerialDispatchQueueScheduler { 22 | 23 | private let _mainQueue: DispatchQueue 24 | 25 | var numberEnqueued: AtomicInt = 0 26 | 27 | /// Initializes new instance of `MainScheduler`. 28 | public init() { 29 | _mainQueue = DispatchQueue.main 30 | super.init(serialQueue: _mainQueue) 31 | } 32 | 33 | /// Singleton instance of `MainScheduler` 34 | public static let instance = MainScheduler() 35 | 36 | /// Singleton instance of `MainScheduler` that always schedules work asynchronously 37 | /// and doesn't perform optimizations for calls scheduled from main queue. 38 | public static let asyncInstance = SerialDispatchQueueScheduler(serialQueue: DispatchQueue.main) 39 | 40 | /// In case this method is called on a background thread it will throw an exception. 41 | public class func ensureExecutingOnScheduler(errorMessage: String? = nil) { 42 | if !DispatchQueue.isMain { 43 | rxFatalError(errorMessage ?? "Executing on backgound thread. Please use `MainScheduler.instance.schedule` to schedule work on main thread.") 44 | } 45 | } 46 | 47 | override func scheduleInternal(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { 48 | let currentNumberEnqueued = AtomicIncrement(&numberEnqueued) 49 | 50 | if DispatchQueue.isMain && currentNumberEnqueued == 1 { 51 | let disposable = action(state) 52 | _ = AtomicDecrement(&numberEnqueued) 53 | return disposable 54 | } 55 | 56 | let cancel = SingleAssignmentDisposable() 57 | 58 | _mainQueue.async { 59 | if !cancel.isDisposed { 60 | _ = action(state) 61 | } 62 | 63 | _ = AtomicDecrement(&self.numberEnqueued) 64 | } 65 | 66 | return cancel 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Reduce.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Reduce.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 4/1/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class ReduceSink : Sink, ObserverType { 10 | typealias ResultType = O.E 11 | typealias Parent = Reduce 12 | 13 | private let _parent: Parent 14 | private var _accumulation: AccumulateType 15 | 16 | init(parent: Parent, observer: O, cancel: Cancelable) { 17 | _parent = parent 18 | _accumulation = parent._seed 19 | 20 | super.init(observer: observer, cancel: cancel) 21 | } 22 | 23 | func on(_ event: Event) { 24 | switch event { 25 | case .next(let value): 26 | do { 27 | _accumulation = try _parent._accumulator(_accumulation, value) 28 | } 29 | catch let e { 30 | forwardOn(.error(e)) 31 | dispose() 32 | } 33 | case .error(let e): 34 | forwardOn(.error(e)) 35 | dispose() 36 | case .completed: 37 | do { 38 | let result = try _parent._mapResult(_accumulation) 39 | forwardOn(.next(result)) 40 | forwardOn(.completed) 41 | dispose() 42 | } 43 | catch let e { 44 | forwardOn(.error(e)) 45 | dispose() 46 | } 47 | } 48 | } 49 | } 50 | 51 | final class Reduce : Producer { 52 | typealias AccumulatorType = (AccumulateType, SourceType) throws -> AccumulateType 53 | typealias ResultSelectorType = (AccumulateType) throws -> ResultType 54 | 55 | fileprivate let _source: Observable 56 | fileprivate let _seed: AccumulateType 57 | fileprivate let _accumulator: AccumulatorType 58 | fileprivate let _mapResult: ResultSelectorType 59 | 60 | init(source: Observable, seed: AccumulateType, accumulator: @escaping AccumulatorType, mapResult: @escaping ResultSelectorType) { 61 | _source = source 62 | _seed = seed 63 | _accumulator = accumulator 64 | _mapResult = mapResult 65 | } 66 | 67 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == ResultType { 68 | let sink = ReduceSink(parent: self, observer: observer, cancel: cancel) 69 | let subscription = _source.subscribe(sink) 70 | return (sink: sink, subscription: subscription) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SingleAssignmentDisposable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SingleAssignmentDisposable.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/15/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /** 10 | Represents a disposable resource which only allows a single assignment of its underlying disposable resource. 11 | 12 | If an underlying disposable resource has already been set, future attempts to set the underlying disposable resource will throw an exception. 13 | */ 14 | public final class SingleAssignmentDisposable : DisposeBase, Disposable, Cancelable { 15 | 16 | fileprivate enum DisposeState: UInt32 { 17 | case disposed = 1 18 | case disposableSet = 2 19 | } 20 | 21 | // Jeej, swift API consistency rules 22 | fileprivate enum DisposeStateInt32: Int32 { 23 | case disposed = 1 24 | case disposableSet = 2 25 | } 26 | 27 | // state 28 | private var _state: AtomicInt = 0 29 | private var _disposable = nil as Disposable? 30 | 31 | /// - returns: A value that indicates whether the object is disposed. 32 | public var isDisposed: Bool { 33 | return AtomicFlagSet(DisposeState.disposed.rawValue, &_state) 34 | } 35 | 36 | /// Initializes a new instance of the `SingleAssignmentDisposable`. 37 | public override init() { 38 | super.init() 39 | } 40 | 41 | /// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined. 42 | /// 43 | /// **Throws exception if the `SingleAssignmentDisposable` has already been assigned to.** 44 | public func setDisposable(_ disposable: Disposable) { 45 | _disposable = disposable 46 | 47 | let previousState = AtomicOr(DisposeState.disposableSet.rawValue, &_state) 48 | 49 | if (previousState & DisposeStateInt32.disposableSet.rawValue) != 0 { 50 | rxFatalError("oldState.disposable != nil") 51 | } 52 | 53 | if (previousState & DisposeStateInt32.disposed.rawValue) != 0 { 54 | disposable.dispose() 55 | _disposable = nil 56 | } 57 | } 58 | 59 | /// Disposes the underlying disposable. 60 | public func dispose() { 61 | let previousState = AtomicOr(DisposeState.disposed.rawValue, &_state) 62 | 63 | if (previousState & DisposeStateInt32.disposed.rawValue) != 0 { 64 | return 65 | } 66 | 67 | if (previousState & DisposeStateInt32.disposableSet.rawValue) != 0 { 68 | guard let disposable = _disposable else { 69 | rxFatalError("Disposable not set") 70 | } 71 | disposable.dispose() 72 | _disposable = nil 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /smck/Parser/ParsingInterface.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParsingInterface.swift 3 | // SMCheckProject 4 | // 5 | // Created by didi on 2017/2/23. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | /* 10 | 语法范例 11 | #@interface SMService (Car) 12 | #@interface SMPickView : UIView 13 | #@interface SMView () 14 | */ 15 | 16 | import Foundation 17 | 18 | class ParsingInterface { 19 | //将完整获取信息结合到object里 20 | class func parsing(line:String, inObject:Object) { 21 | let aLine = line.replacingOccurrences(of: Sb.atInteface, with: "") 22 | let tokens = ParsingBase.createOCTokens(conent: aLine) 23 | 24 | var endNameTf = false //完成类名获取 25 | var inSuperNameTf = false //获取:符号进入获取父类名阶段 26 | var inCategoryTf = false //获取类别 27 | var inProtocolTf = false //获取协议定义 28 | 29 | for tk in tokens { 30 | if !endNameTf && !inSuperNameTf && !inCategoryTf && !inProtocolTf { 31 | inObject.name = tk 32 | endNameTf = true 33 | } else if tk == Sb.colon && endNameTf && !inSuperNameTf && !inCategoryTf && !inProtocolTf { 34 | inSuperNameTf = true 35 | } else if tk == Sb.rBktL && endNameTf && !inCategoryTf && !inProtocolTf { 36 | inCategoryTf = true 37 | } else if inSuperNameTf && !inCategoryTf && !inProtocolTf { 38 | inObject.superName = tk 39 | inSuperNameTf = false 40 | } else if inCategoryTf && tk != Sb.rBktR && !inProtocolTf { 41 | inObject.category = tk 42 | } else if inCategoryTf && tk == Sb.rBktR { 43 | // 检测到右括号说明 Category 检测完毕 44 | inCategoryTf = false 45 | 46 | if inObject.category.isEmpty { 47 | // 为 Extension 添加 void 与 Category 区分开 48 | inObject.category = "void" 49 | } 50 | } else if tk == Sb.agBktL && !inProtocolTf { 51 | inProtocolTf = true 52 | } else if tk != Sb.comma && tk != Sb.agBktR && inProtocolTf { 53 | inObject.usingProtocols.append(tk) 54 | } 55 | } 56 | 57 | } 58 | //获取interface的name 59 | class func parsingNameFrom(line:String) -> String { 60 | guard let name = self.tokensFrom(line: line).first else { 61 | return "" 62 | } 63 | return name 64 | } 65 | 66 | class func tokensFrom(line:String) -> [String] { 67 | let aLine = line.replacingOccurrences(of: Sb.atInteface, with: "") 68 | return ParsingBase.createOCTokens(conent: aLine) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/DisposeBag.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DisposeBag.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/25/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | extension Disposable { 10 | /// Deprecated in favor of `disposed(by:)` 11 | /// 12 | /// **@available(\*, deprecated, message="use disposed(by:) instead")** 13 | /// 14 | /// Adds `self` to `bag`. 15 | /// 16 | /// - parameter bag: `DisposeBag` to add `self` to. 17 | public func addDisposableTo(_ bag: DisposeBag) { 18 | disposed(by: bag) 19 | } 20 | 21 | /// Adds `self` to `bag` 22 | /// 23 | /// - parameter bag: `DisposeBag` to add `self` to. 24 | public func disposed(by bag: DisposeBag) { 25 | bag.insert(self) 26 | } 27 | } 28 | 29 | /** 30 | Thread safe bag that disposes added disposables on `deinit`. 31 | 32 | This returns ARC (RAII) like resource management to `RxSwift`. 33 | 34 | In case contained disposables need to be disposed, just put a different dispose bag 35 | or create a new one in its place. 36 | 37 | self.existingDisposeBag = DisposeBag() 38 | 39 | In case explicit disposal is necessary, there is also `CompositeDisposable`. 40 | */ 41 | public final class DisposeBag: DisposeBase { 42 | 43 | private var _lock = SpinLock() 44 | 45 | // state 46 | private var _disposables = [Disposable]() 47 | private var _isDisposed = false 48 | 49 | /// Constructs new empty dispose bag. 50 | public override init() { 51 | super.init() 52 | } 53 | 54 | /// Adds `disposable` to be disposed when dispose bag is being deinited. 55 | /// 56 | /// - parameter disposable: Disposable to add. 57 | public func insert(_ disposable: Disposable) { 58 | _insert(disposable)?.dispose() 59 | } 60 | 61 | private func _insert(_ disposable: Disposable) -> Disposable? { 62 | _lock.lock(); defer { _lock.unlock() } 63 | if _isDisposed { 64 | return disposable 65 | } 66 | 67 | _disposables.append(disposable) 68 | 69 | return nil 70 | } 71 | 72 | /// This is internal on purpose, take a look at `CompositeDisposable` instead. 73 | private func dispose() { 74 | let oldDisposables = _dispose() 75 | 76 | for disposable in oldDisposables { 77 | disposable.dispose() 78 | } 79 | } 80 | 81 | private func _dispose() -> [Disposable] { 82 | _lock.lock(); defer { _lock.unlock() } 83 | 84 | let disposables = _disposables 85 | 86 | _disposables.removeAll(keepingCapacity: false) 87 | _isDisposed = true 88 | 89 | return disposables 90 | } 91 | 92 | deinit { 93 | dispose() 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 用 Swift 编写的工程代码静态分析命令行工具 smck 2 | ## 前言 3 | 最近几周在用 swift 做一个命令行工具 smck 用来对现有 OC 工程的代码做些分析和处理。日后工程切换成 Swift 可以加上对 Swift 工程代码的支持。昨天看到喵神在微博上说他下周要直播 live coding 一个 swift 的命令行工具,传送门: [现场编程 - 用 Swift 创建命令行工具 fengniao-cli Part1](http://m.quzhiboapp.com/?liveId=391&fromUserId=12049#!/intro/391) ,其实蛮期待。想想跟喵神挺有缘的,最近下了他开发的 iOS 应用 Mail Me,随时能够记录工作和准备讲座时一些灵感,smck 的一些实现还有模块的设计灵感也是通过这个应用随时记录了下来呢,所以也推荐大家使用,真心方便。还有先前 Segmentfault 邀请我这个月31号在他们的直播平台上做个讲座,传送门: [深入剖析 iOS 编译 Clang / LLVM - 戴铭 - SegmentFault 讲堂](https://segmentfault.com/l/1500000008514518) ,先前写过一篇文章,直播可能更利于演示和详细说明一些细节吧。看来这段时间我要跟喵神做好多类似的事情了。smck 的代码今天已经放到了 Github 上,地址:https://github.com/ming1016/smck 4 | 5 | ## smck 可以做哪些事情呢? 6 | * 简单的比如命名规则的检查,按照团队标准来,如所有继承 UIViewController 的命名末尾统一成 VC,继承 JSONModel 的命名末尾统一成 Model,还有特定功能基类的子类按照一定的命名规则来。 7 | * 再比如查找所有中文字符串列出每个字符串分别使用在哪个控件上。 8 | * 根据类是否被初始化或直接调用等规则检查来分析哪些类从来没有调用过来判断是否是没有用的类。 9 | * 对工程质量的检查,比如 NSString,block,NSArray 的属性检查否是为 copy,还有 protocol 是否为 weak,Array 的操作是否使用具有安全操作的 Category 来做等等。 10 | 当然需要检查分析和处理的肯定不止这些,所以在 smck 这个程序设计成了一种非常利于添加各种检查功能模块的结构,通过简单的代码编写每个人或团队都可以方便编写添加各种 checker。 11 | 12 | ## 是怎么做到简单编写就能够添加功能呢? 13 | 因为代码分析的过程会通过一系列已经编写好的 parser 来完成,parser 会完成 token 的分析和上下文还有工程全局分析输出所有节点的数据信息,根据这些完整的信息和已经定义好的一系列具有完整包含关系的结构体就能够进行各种各样功能的定制化了。下面是一些 parser 和功能介绍: 14 | 15 | ![parser](https://github.com/ming1016/smck/blob/master/README/5.png?raw=true) 16 | * ParsingMethod.swift :会返回 Method 结构体,包含了方法名,各个参数,方法内使用过的方法,方法内定义的临时变量等信息。 17 | * ParsingMethodContent.swift :会分析方法内的 token 根据语法形成数组结构进行处理。这里需要处理的东西很多,目前还在根据计划添加更多的数据输出。 18 | * ParsingMacro.swift :处理宏定义,主要是输出 token 给其它 parser 来处理。 19 | * ParsingImport.swift :返回 Import 结构体,包含引入的类名,包名 20 | * ParsingProperty.swift :会分析定义的属性 Property 信息 21 | * ParsingInterface.swift :会根据这个分析出一个文件中定义了多少各类,类的结构体 Object 里类名,父类名,类别名会在这里解析出。 22 | * ParsingProtocol.swift :会将分析出的协议设置到 Object 结构体中。 23 | * ParsingObject.swift : 目前主要是分析出使用过的类的信息。 24 | 25 | 生成的 File 结构体里面套装各个子结构体,断点如图: 26 | ![结构体](https://github.com/ming1016/smck/blob/master/README/6.png?raw=true) 27 | ## 如何调试 smck? 28 | 先填上对应的命令行参数和值,设置参数参考下图。然后运行即可。 29 | ![命令行参数](https://github.com/ming1016/smck/blob/master/README/2.png?raw=true) 30 | ## 导出成命令行工具 31 | 在 Xcode 里选择 Product - Archive - Export 即可,如图: 32 | ![导出](https://github.com/ming1016/smck/blob/master/README/3.png?raw=true) 33 | 执行 34 | ``` 35 | ./smck -o /User/your_project_path 36 | ``` 37 | 输出如下 38 | ![执行效果](https://github.com/ming1016/smck/blob/master/README/4.png?raw=true) 39 | ## 如何编写自己的检查功能? 40 | 由于工程检查规则非常多样化,所以需要编写一些 Plugin,后面我会逐渐抽出一些具有共性的放上来,目前在 Plugin 目录下我放了两个例子,在例子里可以看出来怎么通过订阅 Parser 输出的不同节点的不同数据来进行不同的检查。在控制台管理相关的 Checker 类里关联 Parser 和 Plugin 的代码由于使用了 RxSwift 也变得非常简洁明了,如下: 41 | ```swift 42 | func doO(path:String) { 43 | guard path.characters.count > 0 else { 44 | return 45 | } 46 | UnUseObjectPlugin().plug(ob: ParsingEntire.parsing(path: path)) 47 | } 48 | ``` 49 | 50 | 51 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/HistoricalSchedulerTimeConverter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HistoricalSchedulerTimeConverter.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 12/27/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | import struct Foundation.Date 10 | 11 | /// Converts historial virtual time into real time. 12 | /// 13 | /// Since historical virtual time is also measured in `Date`, this converter is identity function. 14 | public struct HistoricalSchedulerTimeConverter : VirtualTimeConverterType { 15 | /// Virtual time unit used that represents ticks of virtual clock. 16 | public typealias VirtualTimeUnit = RxTime 17 | 18 | /// Virtual time unit used to represent differences of virtual times. 19 | public typealias VirtualTimeIntervalUnit = RxTimeInterval 20 | 21 | /// Returns identical value of argument passed because historical virtual time is equal to real time, just 22 | /// decoupled from local machine clock. 23 | public func convertFromVirtualTime(_ virtualTime: VirtualTimeUnit) -> RxTime { 24 | return virtualTime 25 | } 26 | 27 | /// Returns identical value of argument passed because historical virtual time is equal to real time, just 28 | /// decoupled from local machine clock. 29 | public func convertToVirtualTime(_ time: RxTime) -> VirtualTimeUnit { 30 | return time 31 | } 32 | 33 | /// Returns identical value of argument passed because historical virtual time is equal to real time, just 34 | /// decoupled from local machine clock. 35 | public func convertFromVirtualTimeInterval(_ virtualTimeInterval: VirtualTimeIntervalUnit) -> RxTimeInterval { 36 | return virtualTimeInterval 37 | } 38 | 39 | /// Returns identical value of argument passed because historical virtual time is equal to real time, just 40 | /// decoupled from local machine clock. 41 | public func convertToVirtualTimeInterval(_ timeInterval: RxTimeInterval) -> VirtualTimeIntervalUnit { 42 | return timeInterval 43 | } 44 | 45 | /** 46 | Offsets `Date` by time interval. 47 | 48 | - parameter time: Time. 49 | - parameter timeInterval: Time interval offset. 50 | - returns: Time offsetted by time interval. 51 | */ 52 | public func offsetVirtualTime(_ time: VirtualTimeUnit, offset: VirtualTimeIntervalUnit) -> VirtualTimeUnit { 53 | return time.addingTimeInterval(offset) 54 | } 55 | 56 | /// Compares two `Date`s. 57 | public func compareVirtualTime(_ lhs: VirtualTimeUnit, _ rhs: VirtualTimeUnit) -> VirtualTimeComparison { 58 | switch lhs.compare(rhs as Date) { 59 | case .orderedAscending: 60 | return .lessThan 61 | case .orderedSame: 62 | return .equal 63 | case .orderedDescending: 64 | return .greaterThan 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Observable+Aggregate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Observable+Aggregate.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/22/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | // MARK: reduce 10 | 11 | extension ObservableType { 12 | 13 | /** 14 | Applies an `accumulator` function over an observable sequence, returning the result of the aggregation as a single element in the result sequence. The specified `seed` value is used as the initial accumulator value. 15 | 16 | For aggregation behavior with incremental intermediate results, see `scan`. 17 | 18 | - seealso: [reduce operator on reactivex.io](http://reactivex.io/documentation/operators/reduce.html) 19 | 20 | - parameter seed: The initial accumulator value. 21 | - parameter accumulator: A accumulator function to be invoked on each element. 22 | - parameter mapResult: A function to transform the final accumulator value into the result value. 23 | - returns: An observable sequence containing a single element with the final accumulator value. 24 | */ 25 | public func reduce(_ seed: A, accumulator: @escaping (A, E) throws -> A, mapResult: @escaping (A) throws -> R) 26 | -> Observable { 27 | return Reduce(source: self.asObservable(), seed: seed, accumulator: accumulator, mapResult: mapResult) 28 | } 29 | 30 | /** 31 | Applies an `accumulator` function over an observable sequence, returning the result of the aggregation as a single element in the result sequence. The specified `seed` value is used as the initial accumulator value. 32 | 33 | For aggregation behavior with incremental intermediate results, see `scan`. 34 | 35 | - seealso: [reduce operator on reactivex.io](http://reactivex.io/documentation/operators/reduce.html) 36 | 37 | - parameter seed: The initial accumulator value. 38 | - parameter accumulator: A accumulator function to be invoked on each element. 39 | - returns: An observable sequence containing a single element with the final accumulator value. 40 | */ 41 | public func reduce(_ seed: A, accumulator: @escaping (A, E) throws -> A) 42 | -> Observable { 43 | return Reduce(source: self.asObservable(), seed: seed, accumulator: accumulator, mapResult: { $0 }) 44 | } 45 | 46 | /** 47 | Converts an Observable into another Observable that emits the whole sequence as a single array and then terminates. 48 | 49 | For aggregation behavior see `reduce`. 50 | 51 | - seealso: [toArray operator on reactivex.io](http://reactivex.io/documentation/operators/to.html) 52 | 53 | - returns: An observable sequence containing all the emitted elements as array. 54 | */ 55 | public func toArray() 56 | -> Observable<[E]> { 57 | return ToArray(source: self.asObservable()) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ObserveOnSerialDispatchQueue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObserveOnSerialDispatchQueue.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 5/31/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | #if TRACE_RESOURCES 10 | fileprivate var _numberOfSerialDispatchQueueObservables: AtomicInt = 0 11 | extension Resources { 12 | /** 13 | Counts number of `SerialDispatchQueueObservables`. 14 | 15 | Purposed for unit tests. 16 | */ 17 | public static var numberOfSerialDispatchQueueObservables: Int32 { 18 | return _numberOfSerialDispatchQueueObservables.valueSnapshot() 19 | } 20 | } 21 | #endif 22 | 23 | final class ObserveOnSerialDispatchQueueSink : ObserverBase { 24 | let scheduler: SerialDispatchQueueScheduler 25 | let observer: O 26 | 27 | let cancel: Cancelable 28 | 29 | var cachedScheduleLambda: ((ObserveOnSerialDispatchQueueSink, Event) -> Disposable)! 30 | 31 | init(scheduler: SerialDispatchQueueScheduler, observer: O, cancel: Cancelable) { 32 | self.scheduler = scheduler 33 | self.observer = observer 34 | self.cancel = cancel 35 | super.init() 36 | 37 | cachedScheduleLambda = { sink, event in 38 | sink.observer.on(event) 39 | 40 | if event.isStopEvent { 41 | sink.dispose() 42 | } 43 | 44 | return Disposables.create() 45 | } 46 | } 47 | 48 | override func onCore(_ event: Event) { 49 | let _ = self.scheduler.schedule((self, event), action: cachedScheduleLambda) 50 | } 51 | 52 | override func dispose() { 53 | super.dispose() 54 | 55 | cancel.dispose() 56 | } 57 | } 58 | 59 | final class ObserveOnSerialDispatchQueue : Producer { 60 | let scheduler: SerialDispatchQueueScheduler 61 | let source: Observable 62 | 63 | init(source: Observable, scheduler: SerialDispatchQueueScheduler) { 64 | self.scheduler = scheduler 65 | self.source = source 66 | 67 | #if TRACE_RESOURCES 68 | let _ = Resources.incrementTotal() 69 | let _ = AtomicIncrement(&_numberOfSerialDispatchQueueObservables) 70 | #endif 71 | } 72 | 73 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == E { 74 | let sink = ObserveOnSerialDispatchQueueSink(scheduler: scheduler, observer: observer, cancel: cancel) 75 | let subscription = source.subscribe(sink) 76 | return (sink: sink, subscription: subscription) 77 | } 78 | 79 | #if TRACE_RESOURCES 80 | deinit { 81 | let _ = Resources.decrementTotal() 82 | let _ = AtomicDecrement(&_numberOfSerialDispatchQueueObservables) 83 | } 84 | #endif 85 | } 86 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/AsyncLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AsyncLock.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/21/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /** 10 | In case nobody holds this lock, the work will be queued and executed immediately 11 | on thread that is requesting lock. 12 | 13 | In case there is somebody currently holding that lock, action will be enqueued. 14 | When owned of the lock finishes with it's processing, it will also execute 15 | and pending work. 16 | 17 | That means that enqueued work could possibly be executed later on a different thread. 18 | */ 19 | final class AsyncLock 20 | : Disposable 21 | , Lock 22 | , SynchronizedDisposeType { 23 | typealias Action = () -> Void 24 | 25 | var _lock = SpinLock() 26 | 27 | private var _queue: Queue = Queue(capacity: 0) 28 | 29 | private var _isExecuting: Bool = false 30 | private var _hasFaulted: Bool = false 31 | 32 | // lock { 33 | func lock() { 34 | _lock.lock() 35 | } 36 | 37 | func unlock() { 38 | _lock.unlock() 39 | } 40 | // } 41 | 42 | private func enqueue(_ action: I) -> I? { 43 | _lock.lock(); defer { _lock.unlock() } // { 44 | if _hasFaulted { 45 | return nil 46 | } 47 | 48 | if _isExecuting { 49 | _queue.enqueue(action) 50 | return nil 51 | } 52 | 53 | _isExecuting = true 54 | 55 | return action 56 | // } 57 | } 58 | 59 | private func dequeue() -> I? { 60 | _lock.lock(); defer { _lock.unlock() } // { 61 | if _queue.count > 0 { 62 | return _queue.dequeue() 63 | } 64 | else { 65 | _isExecuting = false 66 | return nil 67 | } 68 | // } 69 | } 70 | 71 | func invoke(_ action: I) { 72 | let firstEnqueuedAction = enqueue(action) 73 | 74 | if let firstEnqueuedAction = firstEnqueuedAction { 75 | firstEnqueuedAction.invoke() 76 | } 77 | else { 78 | // action is enqueued, it's somebody else's concern now 79 | return 80 | } 81 | 82 | while true { 83 | let nextAction = dequeue() 84 | 85 | if let nextAction = nextAction { 86 | nextAction.invoke() 87 | } 88 | else { 89 | return 90 | } 91 | } 92 | } 93 | 94 | func dispose() { 95 | synchronizedDispose() 96 | } 97 | 98 | func _synchronized_dispose() { 99 | _queue = Queue(capacity: 0) 100 | _hasFaulted = true 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SwitchIfEmpty.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwitchIfEmpty.swift 3 | // RxSwift 4 | // 5 | // Created by sergdort on 23/12/2016. 6 | // Copyright © 2016 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class SwitchIfEmpty: Producer { 10 | 11 | private let _source: Observable 12 | private let _ifEmpty: Observable 13 | 14 | init(source: Observable, ifEmpty: Observable) { 15 | _source = source 16 | _ifEmpty = ifEmpty 17 | } 18 | 19 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 20 | let sink = SwitchIfEmptySink(ifEmpty: _ifEmpty, 21 | observer: observer, 22 | cancel: cancel) 23 | let subscription = sink.run(_source.asObservable()) 24 | 25 | return (sink: sink, subscription: subscription) 26 | } 27 | } 28 | 29 | final class SwitchIfEmptySink: Sink 30 | , ObserverType { 31 | typealias E = O.E 32 | 33 | private let _ifEmpty: Observable 34 | private var _isEmpty = true 35 | private let _ifEmptySubscription = SingleAssignmentDisposable() 36 | 37 | init(ifEmpty: Observable, observer: O, cancel: Cancelable) { 38 | _ifEmpty = ifEmpty 39 | super.init(observer: observer, cancel: cancel) 40 | } 41 | 42 | func run(_ source: Observable) -> Disposable { 43 | let subscription = source.subscribe(self) 44 | return Disposables.create(subscription, _ifEmptySubscription) 45 | } 46 | 47 | func on(_ event: Event) { 48 | switch event { 49 | case .next: 50 | _isEmpty = false 51 | forwardOn(event) 52 | case .error: 53 | forwardOn(event) 54 | dispose() 55 | case .completed: 56 | guard _isEmpty else { 57 | forwardOn(.completed) 58 | dispose() 59 | return 60 | } 61 | let ifEmptySink = SwitchIfEmptySinkIter(parent: self) 62 | _ifEmptySubscription.setDisposable(_ifEmpty.subscribe(ifEmptySink)) 63 | } 64 | } 65 | } 66 | 67 | final class SwitchIfEmptySinkIter 68 | : ObserverType { 69 | typealias E = O.E 70 | typealias Parent = SwitchIfEmptySink 71 | 72 | private let _parent: Parent 73 | 74 | init(parent: Parent) { 75 | _parent = parent 76 | } 77 | 78 | func on(_ event: Event) { 79 | switch event { 80 | case .next: 81 | _parent.forwardOn(event) 82 | case .error: 83 | _parent.forwardOn(event) 84 | _parent.dispose() 85 | case .completed: 86 | _parent.forwardOn(event) 87 | _parent.dispose() 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/RefCount.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RefCount.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 3/5/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class RefCountSink 10 | : Sink 11 | , ObserverType where CO.E == O.E { 12 | typealias Element = O.E 13 | typealias Parent = RefCount 14 | 15 | private let _parent: Parent 16 | 17 | init(parent: Parent, observer: O, cancel: Cancelable) { 18 | _parent = parent 19 | super.init(observer: observer, cancel: cancel) 20 | } 21 | 22 | func run() -> Disposable { 23 | let subscription = _parent._source.subscribe(self) 24 | 25 | _parent._lock.lock(); defer { _parent._lock.unlock() } // { 26 | if _parent._count == 0 { 27 | _parent._count = 1 28 | _parent._connectableSubscription = _parent._source.connect() 29 | } 30 | else { 31 | _parent._count = _parent._count + 1 32 | } 33 | // } 34 | 35 | return Disposables.create { 36 | subscription.dispose() 37 | self._parent._lock.lock(); defer { self._parent._lock.unlock() } // { 38 | if self._parent._count == 1 { 39 | self._parent._count = 0 40 | guard let connectableSubscription = self._parent._connectableSubscription else { 41 | return 42 | } 43 | 44 | connectableSubscription.dispose() 45 | self._parent._connectableSubscription = nil 46 | } 47 | else if self._parent._count > 1 { 48 | self._parent._count = self._parent._count - 1 49 | } 50 | else { 51 | rxFatalError("Something went wrong with RefCount disposing mechanism") 52 | } 53 | // } 54 | } 55 | } 56 | 57 | func on(_ event: Event) { 58 | switch event { 59 | case .next: 60 | forwardOn(event) 61 | case .error, .completed: 62 | forwardOn(event) 63 | dispose() 64 | } 65 | } 66 | } 67 | 68 | final class RefCount: Producer { 69 | fileprivate let _lock = RecursiveLock() 70 | 71 | // state 72 | fileprivate var _count = 0 73 | fileprivate var _connectableSubscription = nil as Disposable? 74 | 75 | fileprivate let _source: CO 76 | 77 | init(source: CO) { 78 | _source = source 79 | } 80 | 81 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == CO.E { 82 | let sink = RefCountSink(parent: self, observer: observer, cancel: cancel) 83 | let subscription = sink.run() 84 | return (sink: sink, subscription: subscription) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/SchedulerType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SchedulerType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/8/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | import struct Foundation.TimeInterval 10 | import struct Foundation.Date 11 | 12 | // Type that represents time interval in the context of RxSwift. 13 | public typealias RxTimeInterval = TimeInterval 14 | 15 | /// Type that represents absolute time in the context of RxSwift. 16 | public typealias RxTime = Date 17 | 18 | /// Represents an object that schedules units of work. 19 | public protocol SchedulerType: ImmediateSchedulerType { 20 | 21 | /// - returns: Current time. 22 | var now : RxTime { 23 | get 24 | } 25 | 26 | /** 27 | Schedules an action to be executed. 28 | 29 | - parameter state: State passed to the action to be executed. 30 | - parameter dueTime: Relative time after which to execute the action. 31 | - parameter action: Action to be executed. 32 | - returns: The disposable object used to cancel the scheduled action (best effort). 33 | */ 34 | func scheduleRelative(_ state: StateType, dueTime: RxTimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable 35 | 36 | /** 37 | Schedules a periodic piece of work. 38 | 39 | - parameter state: State passed to the action to be executed. 40 | - parameter startAfter: Period after which initial work should be run. 41 | - parameter period: Period for running the work periodically. 42 | - parameter action: Action to be executed. 43 | - returns: The disposable object used to cancel the scheduled action (best effort). 44 | */ 45 | func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable 46 | } 47 | 48 | extension SchedulerType { 49 | 50 | /** 51 | Periodic task will be emulated using recursive scheduling. 52 | 53 | - parameter state: Initial state passed to the action upon the first iteration. 54 | - parameter startAfter: Period after which initial work should be run. 55 | - parameter period: Period for running the work periodically. 56 | - returns: The disposable object used to cancel the scheduled recurring action (best effort). 57 | */ 58 | public func schedulePeriodic(_ state: StateType, startAfter: RxTimeInterval, period: RxTimeInterval, action: @escaping (StateType) -> StateType) -> Disposable { 59 | let schedule = SchedulePeriodicRecursive(scheduler: self, startAfter: startAfter, period: period, action: action, state: state) 60 | 61 | return schedule.start() 62 | } 63 | 64 | func scheduleRecursive(_ state: State, dueTime: RxTimeInterval, action: @escaping (State, AnyRecursiveScheduler) -> ()) -> Disposable { 65 | let scheduler = AnyRecursiveScheduler(scheduler: self, action: action) 66 | 67 | scheduler.schedule(state, dueTime: dueTime) 68 | 69 | return Disposables.create(with: scheduler.dispose) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /smck/Parser/CSSParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CSSParser.swift 3 | // smck 4 | // 5 | // Created by DaiMing on 2017/4/19. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum CSSParseError: Swift.Error { 12 | case unexpectedToken(String) 13 | case unexpectedEOF 14 | } 15 | 16 | class CSSParser { 17 | let tokens: [String] 18 | var index = 0 19 | 20 | init(tokens:[String]) { 21 | self.tokens = tokens 22 | } 23 | func parseFile() throws -> CSSFile { 24 | let file = CSSFile() 25 | while currentToken != nil { 26 | let selector = try parseSelector() 27 | file.addSelector(selector) 28 | } 29 | return file 30 | } 31 | 32 | func parseSelector() throws -> CSSSelector { 33 | guard currentToken != nil else { 34 | throw CSSParseError.unexpectedEOF 35 | } 36 | 37 | var psStep = 0 //0:初始,1:开始处理属性名,2:开始处理属性值,3结束一个selector 38 | 39 | var selectorName = "" 40 | var propertys = [String: String]() 41 | var currentAttributeName = "" 42 | 43 | while let tk = currentToken { 44 | 45 | if psStep == 2 { 46 | var vr = "" 47 | while let tok = currentToken { 48 | if tok == ";" { 49 | propertys[currentAttributeName] = vr 50 | psStep = 1 51 | consumeToken() 52 | break 53 | } else { 54 | vr.append(tok) 55 | } 56 | consumeToken() 57 | } 58 | continue 59 | } 60 | 61 | if psStep == 1 { 62 | currentAttributeName = "" 63 | if tk == "}" { 64 | consumeToken() 65 | break 66 | } 67 | while let tok = currentToken { 68 | if tok == ":" { 69 | psStep = 2 70 | consumeToken() 71 | break 72 | } else { 73 | currentAttributeName.append(tok) 74 | } 75 | consumeToken() 76 | } 77 | continue 78 | } 79 | 80 | if psStep == 0 { 81 | if tk == "{" { 82 | psStep = 1 83 | consumeToken() 84 | continue 85 | } 86 | selectorName.append(tk) 87 | consumeToken() 88 | continue 89 | } 90 | } 91 | 92 | return CSSSelector(selectorName: selectorName, propertys: propertys) 93 | } 94 | 95 | /*------------------*/ 96 | var currentToken: String? { 97 | return index < tokens.count ? tokens[index] : nil 98 | } 99 | func consumeToken(n: Int = 1) { 100 | index += n 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Debug.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Debug.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 5/2/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | import struct Foundation.Date 10 | import class Foundation.DateFormatter 11 | 12 | let dateFormat = "yyyy-MM-dd HH:mm:ss.SSS" 13 | 14 | func logEvent(_ identifier: String, dateFormat: DateFormatter, content: String) { 15 | print("\(dateFormat.string(from: Date())): \(identifier) -> \(content)") 16 | } 17 | 18 | final class DebugSink : Sink, ObserverType where O.E == Source.E { 19 | typealias Element = O.E 20 | typealias Parent = Debug 21 | 22 | private let _parent: Parent 23 | private let _timestampFormatter = DateFormatter() 24 | 25 | init(parent: Parent, observer: O, cancel: Cancelable) { 26 | _parent = parent 27 | _timestampFormatter.dateFormat = dateFormat 28 | 29 | logEvent(_parent._identifier, dateFormat: _timestampFormatter, content: "subscribed") 30 | 31 | super.init(observer: observer, cancel: cancel) 32 | } 33 | 34 | func on(_ event: Event) { 35 | let maxEventTextLength = 40 36 | let eventText = "\(event)" 37 | 38 | let eventNormalized = (eventText.characters.count > maxEventTextLength) && _parent._trimOutput 39 | ? String(eventText.characters.prefix(maxEventTextLength / 2)) + "..." + String(eventText.characters.suffix(maxEventTextLength / 2)) 40 | : eventText 41 | 42 | logEvent(_parent._identifier, dateFormat: _timestampFormatter, content: "Event \(eventNormalized)") 43 | 44 | forwardOn(event) 45 | if event.isStopEvent { 46 | dispose() 47 | } 48 | } 49 | 50 | override func dispose() { 51 | if !self.disposed { 52 | logEvent(_parent._identifier, dateFormat: _timestampFormatter, content: "isDisposed") 53 | } 54 | super.dispose() 55 | } 56 | } 57 | 58 | final class Debug : Producer { 59 | fileprivate let _identifier: String 60 | fileprivate let _trimOutput: Bool 61 | fileprivate let _source: Source 62 | 63 | init(source: Source, identifier: String?, trimOutput: Bool, file: String, line: UInt, function: String) { 64 | _trimOutput = trimOutput 65 | if let identifier = identifier { 66 | _identifier = identifier 67 | } 68 | else { 69 | let trimmedFile: String 70 | if let lastIndex = file.lastIndexOf("/") { 71 | trimmedFile = file[file.index(after: lastIndex) ..< file.endIndex] 72 | } 73 | else { 74 | trimmedFile = file 75 | } 76 | _identifier = "\(trimmedFile):\(line) (\(function))" 77 | } 78 | _source = source 79 | } 80 | 81 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Source.E { 82 | let sink = DebugSink(parent: self, observer: observer, cancel: cancel) 83 | let subscription = _source.subscribe(sink) 84 | return (sink: sink, subscription: subscription) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Debounce.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Debounce.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 9/11/16. 6 | // Copyright © 2016 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class DebounceSink 10 | : Sink 11 | , ObserverType 12 | , LockOwnerType 13 | , SynchronizedOnType { 14 | typealias Element = O.E 15 | typealias ParentType = Debounce 16 | 17 | private let _parent: ParentType 18 | 19 | let _lock = RecursiveLock() 20 | 21 | // state 22 | private var _id = 0 as UInt64 23 | private var _value: Element? = nil 24 | 25 | let cancellable = SerialDisposable() 26 | 27 | init(parent: ParentType, observer: O, cancel: Cancelable) { 28 | _parent = parent 29 | 30 | super.init(observer: observer, cancel: cancel) 31 | } 32 | 33 | func run() -> Disposable { 34 | let subscription = _parent._source.subscribe(self) 35 | 36 | return Disposables.create(subscription, cancellable) 37 | } 38 | 39 | func on(_ event: Event) { 40 | synchronizedOn(event) 41 | } 42 | 43 | func _synchronized_on(_ event: Event) { 44 | switch event { 45 | case .next(let element): 46 | _id = _id &+ 1 47 | let currentId = _id 48 | _value = element 49 | 50 | 51 | let scheduler = _parent._scheduler 52 | let dueTime = _parent._dueTime 53 | 54 | let d = SingleAssignmentDisposable() 55 | self.cancellable.disposable = d 56 | d.setDisposable(scheduler.scheduleRelative(currentId, dueTime: dueTime, action: self.propagate)) 57 | case .error: 58 | _value = nil 59 | forwardOn(event) 60 | dispose() 61 | case .completed: 62 | if let value = _value { 63 | _value = nil 64 | forwardOn(.next(value)) 65 | } 66 | forwardOn(.completed) 67 | dispose() 68 | } 69 | } 70 | 71 | func propagate(_ currentId: UInt64) -> Disposable { 72 | _lock.lock(); defer { _lock.unlock() } // { 73 | let originalValue = _value 74 | 75 | if let value = originalValue, _id == currentId { 76 | _value = nil 77 | forwardOn(.next(value)) 78 | } 79 | // } 80 | return Disposables.create() 81 | } 82 | } 83 | 84 | final class Debounce : Producer { 85 | 86 | fileprivate let _source: Observable 87 | fileprivate let _dueTime: RxTimeInterval 88 | fileprivate let _scheduler: SchedulerType 89 | 90 | init(source: Observable, dueTime: RxTimeInterval, scheduler: SchedulerType) { 91 | _source = source 92 | _dueTime = dueTime 93 | _scheduler = scheduler 94 | } 95 | 96 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 97 | let sink = DebounceSink(parent: self, observer: observer, cancel: cancel) 98 | let subscription = sink.run() 99 | return (sink: sink, subscription: subscription) 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Platform.Linux.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Platform.Linux.swift 3 | // Platform 4 | // 5 | // Created by Krunoslav Zaher on 12/29/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | #if os(Linux) 10 | 11 | import XCTest 12 | import Glibc 13 | import SwiftShims 14 | import class Foundation.Thread 15 | 16 | final class AtomicInt { 17 | typealias IntegerLiteralType = Int 18 | fileprivate var value: Int32 = 0 19 | fileprivate var _lock = RecursiveLock() 20 | 21 | func lock() { 22 | _lock.lock() 23 | } 24 | func unlock() { 25 | _lock.unlock() 26 | } 27 | 28 | func valueSnapshot() -> Int32 { 29 | return value 30 | } 31 | } 32 | 33 | extension AtomicInt: ExpressibleByIntegerLiteral { 34 | convenience init(integerLiteral value: Int) { 35 | self.init() 36 | self.value = Int32(value) 37 | } 38 | } 39 | 40 | func >(lhs: AtomicInt, rhs: Int32) -> Bool { 41 | return lhs.value > rhs 42 | } 43 | func ==(lhs: AtomicInt, rhs: Int32) -> Bool { 44 | return lhs.value == rhs 45 | } 46 | 47 | func AtomicFlagSet(_ mask: UInt32, _ atomic: inout AtomicInt) -> Bool { 48 | atomic.lock(); defer { atomic.unlock() } 49 | return (atomic.value & Int32(mask)) != 0 50 | } 51 | 52 | func AtomicOr(_ mask: UInt32, _ atomic: inout AtomicInt) -> Int32 { 53 | atomic.lock(); defer { atomic.unlock() } 54 | let value = atomic.value 55 | atomic.value |= Int32(mask) 56 | return value 57 | } 58 | 59 | func AtomicIncrement(_ atomic: inout AtomicInt) -> Int32 { 60 | atomic.lock(); defer { atomic.unlock() } 61 | atomic.value += 1 62 | return atomic.value 63 | } 64 | 65 | func AtomicDecrement(_ atomic: inout AtomicInt) -> Int32 { 66 | atomic.lock(); defer { atomic.unlock() } 67 | atomic.value -= 1 68 | return atomic.value 69 | } 70 | 71 | func AtomicCompareAndSwap(_ l: Int32, _ r: Int32, _ atomic: inout AtomicInt) -> Bool { 72 | atomic.lock(); defer { atomic.unlock() } 73 | if atomic.value == l { 74 | atomic.value = r 75 | return true 76 | } 77 | 78 | return false 79 | } 80 | 81 | extension Thread { 82 | 83 | static func setThreadLocalStorageValue(_ value: T?, forKey key: String) { 84 | let currentThread = Thread.current 85 | var threadDictionary = currentThread.threadDictionary 86 | 87 | if let newValue = value { 88 | threadDictionary[key] = newValue 89 | } 90 | else { 91 | threadDictionary[key] = nil 92 | } 93 | 94 | currentThread.threadDictionary = threadDictionary 95 | } 96 | 97 | static func getThreadLocalStorageValueForKey(_ key: String) -> T? { 98 | let currentThread = Thread.current 99 | let threadDictionary = currentThread.threadDictionary 100 | 101 | return threadDictionary[key] as? T 102 | } 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ShareReplay1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShareReplay1.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/10/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | // optimized version of share replay for most common case 10 | final class ShareReplay1 11 | : Observable 12 | , ObserverType 13 | , SynchronizedUnsubscribeType { 14 | 15 | typealias DisposeKey = Bag>.KeyType 16 | 17 | private let _source: Observable 18 | 19 | private let _lock = RecursiveLock() 20 | 21 | private var _connection: SingleAssignmentDisposable? 22 | private var _element: Element? 23 | private var _stopped = false 24 | private var _stopEvent = nil as Event? 25 | private var _observers = Bag<(Event) -> ()>() 26 | 27 | init(source: Observable) { 28 | self._source = source 29 | } 30 | 31 | override func subscribe(_ observer: O) -> Disposable where O.E == E { 32 | _lock.lock() 33 | let result = _synchronized_subscribe(observer) 34 | _lock.unlock() 35 | return result 36 | } 37 | 38 | func _synchronized_subscribe(_ observer: O) -> Disposable where O.E == E { 39 | if let element = self._element { 40 | observer.on(.next(element)) 41 | } 42 | 43 | if let stopEvent = self._stopEvent { 44 | observer.on(stopEvent) 45 | return Disposables.create() 46 | } 47 | 48 | let initialCount = self._observers.count 49 | 50 | let disposeKey = self._observers.insert(observer.on) 51 | 52 | if initialCount == 0 { 53 | let connection = SingleAssignmentDisposable() 54 | _connection = connection 55 | 56 | connection.setDisposable(self._source.subscribe(self)) 57 | } 58 | 59 | return SubscriptionDisposable(owner: self, key: disposeKey) 60 | } 61 | 62 | func synchronizedUnsubscribe(_ disposeKey: DisposeKey) { 63 | _lock.lock() 64 | _synchronized_unsubscribe(disposeKey) 65 | _lock.unlock() 66 | } 67 | 68 | func _synchronized_unsubscribe(_ disposeKey: DisposeKey) { 69 | // if already unsubscribed, just return 70 | if self._observers.removeKey(disposeKey) == nil { 71 | return 72 | } 73 | 74 | if _observers.count == 0 { 75 | _connection?.dispose() 76 | _connection = nil 77 | } 78 | } 79 | 80 | func on(_ event: Event) { 81 | dispatch(_synchronized_on(event), event) 82 | } 83 | 84 | func _synchronized_on(_ event: Event) -> Bag<(Event) -> ()> { 85 | _lock.lock(); defer { _lock.unlock() } 86 | if _stopped { 87 | return Bag() 88 | } 89 | 90 | switch event { 91 | case .next(let element): 92 | _element = element 93 | case .error, .completed: 94 | _stopEvent = event 95 | _stopped = true 96 | _connection?.dispose() 97 | _connection = nil 98 | } 99 | 100 | return _observers 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/VirtualTimeConverterType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VirtualTimeConverterType.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 12/23/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | /// Parametrization for virtual time used by `VirtualTimeScheduler`s. 10 | public protocol VirtualTimeConverterType { 11 | /// Virtual time unit used that represents ticks of virtual clock. 12 | associatedtype VirtualTimeUnit 13 | 14 | /// Virtual time unit used to represent differences of virtual times. 15 | associatedtype VirtualTimeIntervalUnit 16 | 17 | /** 18 | Converts virtual time to real time. 19 | 20 | - parameter virtualTime: Virtual time to convert to `Date`. 21 | - returns: `Date` corresponding to virtual time. 22 | */ 23 | func convertFromVirtualTime(_ virtualTime: VirtualTimeUnit) -> RxTime 24 | 25 | /** 26 | Converts real time to virtual time. 27 | 28 | - parameter time: `Date` to convert to virtual time. 29 | - returns: Virtual time corresponding to `Date`. 30 | */ 31 | func convertToVirtualTime(_ time: RxTime) -> VirtualTimeUnit 32 | 33 | /** 34 | Converts from virtual time interval to `NSTimeInterval`. 35 | 36 | - parameter virtualTimeInterval: Virtual time interval to convert to `NSTimeInterval`. 37 | - returns: `NSTimeInterval` corresponding to virtual time interval. 38 | */ 39 | func convertFromVirtualTimeInterval(_ virtualTimeInterval: VirtualTimeIntervalUnit) -> RxTimeInterval 40 | 41 | /** 42 | Converts from virtual time interval to `NSTimeInterval`. 43 | 44 | - parameter timeInterval: `NSTimeInterval` to convert to virtual time interval. 45 | - returns: Virtual time interval corresponding to time interval. 46 | */ 47 | func convertToVirtualTimeInterval(_ timeInterval: RxTimeInterval) -> VirtualTimeIntervalUnit 48 | 49 | /** 50 | Offsets virtual time by virtual time interval. 51 | 52 | - parameter time: Virtual time. 53 | - parameter offset: Virtual time interval. 54 | - returns: Time corresponding to time offsetted by virtual time interval. 55 | */ 56 | func offsetVirtualTime(_ time: VirtualTimeUnit, offset: VirtualTimeIntervalUnit) -> VirtualTimeUnit 57 | 58 | /** 59 | This is aditional abstraction because `Date` is unfortunately not comparable. 60 | Extending `Date` with `Comparable` would be too risky because of possible collisions with other libraries. 61 | */ 62 | func compareVirtualTime(_ lhs: VirtualTimeUnit, _ rhs: VirtualTimeUnit) -> VirtualTimeComparison 63 | } 64 | 65 | /** 66 | Virtual time comparison result. 67 | 68 | This is aditional abstraction because `Date` is unfortunately not comparable. 69 | Extending `Date` with `Comparable` would be too risky because of possible collisions with other libraries. 70 | */ 71 | public enum VirtualTimeComparison { 72 | /// lhs < rhs. 73 | case lessThan 74 | /// lhs == rhs. 75 | case equal 76 | /// lhs > rhs. 77 | case greaterThan 78 | } 79 | 80 | extension VirtualTimeComparison { 81 | /// lhs < rhs. 82 | var lessThen: Bool { 83 | return self == .lessThan 84 | } 85 | 86 | /// lhs > rhs 87 | var greaterThan: Bool { 88 | return self == .greaterThan 89 | } 90 | 91 | /// lhs == rhs 92 | var equal: Bool { 93 | return self == .equal 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /smck/Plugin/UnUseObjectPlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UnUseObjectPlugin.swift 3 | // SMCheckProjectCL 4 | // 5 | // Created by didi on 2017/3/10. 6 | // Copyright © 2017年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class UnUseObjectPlugin { 12 | var allObjects = [String:Object]() 13 | var allUsedObjects = [String:Object]() 14 | var whiteList = ["AppDelegate","DCHomeDriverDataSource","DCSocialModule","DCGuideViewBubble","DCHomePassengerDataSource","DCHomeOperationPopView","DCActivityGuideStartUpWelcome"] //定义白名单,因为有些是在 C 方法里用了,但是目前还没有处理 c 的方法 15 | var whiteSuperList = ["JSONModel","TRBaseModel","DCBaseModel","UIViewController","DCBaseViewController","DCBaseComponent","UITableViewCell"] //白名单父类 16 | 17 | func plug(ob:Observable) { 18 | _ = ob.subscribe(onNext: { result in 19 | if result is Dictionary { 20 | let dic = result as! Dictionary 21 | if dic["currentParsingFileDes"] is String { 22 | Console.outPrint("\(String(describing: dic["currentParsingFileDes"]))") 23 | } 24 | if dic["firstRoundAFile"] is File { 25 | let aFile = dic["firstRoundAFile"] as! File 26 | // Console.outPrint("\(aFile.name)") 27 | if aFile.name.hasSuffix("Request.h") { 28 | // Console.outPrint("\(aFile.path)") 29 | } 30 | } 31 | if dic["allObjects"] is [String:Object] { 32 | self.allObjects = dic["allObjects"] as! [String:Object] 33 | } 34 | if dic["allUsedObjects"] is [String:Object] { 35 | self.allUsedObjects = dic["allUsedObjects"] as! [String:Object] 36 | } 37 | } 38 | 39 | }, onCompleted: { 40 | Console.outPrint("无用类", to: .description) 41 | //遍历对比出无用的类 42 | var allUnUsedObjects = [String:Object]() 43 | for (key, value) in self.allObjects { 44 | guard let _ = self.allUsedObjects[key] else { 45 | if value.category.characters.count > 0 || self.whiteList.contains(value.name) { 46 | } else { 47 | if key == "DCOrderlistMyTripSegmentViewController" { 48 | 49 | } 50 | let obj = self.finalSuperObj(obj: value) 51 | //supername。除了 supername 外还要考虑 category 自己 name 可能就是系统的情况 52 | if self.whiteSuperList.contains(obj.superName) || self.whiteSuperList.contains(obj.name) || key.hasSuffix("Unit") || key.hasSuffix("Com") || key.hasSuffix("Cell") { 53 | 54 | } else { 55 | Console.outPrint("\(key)") 56 | allUnUsedObjects[key] = value 57 | } 58 | 59 | } 60 | continue 61 | } // end guard 62 | } // end for 63 | }) // end subscribe 64 | } // end func 65 | 66 | //递归查找最终父类 67 | func finalSuperObj(obj:Object) -> Object { 68 | guard let sObj = self.allObjects[obj.superName] else { 69 | return obj 70 | } 71 | if self.whiteSuperList.contains(sObj.name) { 72 | return sObj 73 | } 74 | return self.finalSuperObj(obj: sObj) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /smck/Parser/ParsingMethod.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParsingMethod.swift 3 | // SMCheckProject 4 | // 5 | // Created by daiming on 2016/10/20. 6 | // Copyright © 2016年 Starming. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class ParsingMethod { 12 | class func parsing(tokens:Array) -> Method { 13 | var mtd = Method() 14 | var returnTypeTf = false //是否取得返回类型 15 | var parsingTf = false //解析中 16 | var bracketCount = 0 //括弧计数 17 | var step = 0 //1获取参数名,2获取参数类型,3获取iName 18 | var types = [String]() 19 | var methodParam = MethodParam() 20 | //print("\(arr)") 21 | for var tk in tokens { 22 | tk = tk.replacingOccurrences(of: Sb.newLine, with: "") 23 | if (tk == Sb.semicolon || tk == Sb.braceL) && step != 1 { 24 | var shouldAdd = false 25 | 26 | if mtd.params.count > 1 { 27 | //处理这种- (void)initWithC:(type)m m2:(type2)i, ... NS_REQUIRES_NIL_TERMINATION;入参为多参数情况 28 | if methodParam.type.characters.count > 0 { 29 | shouldAdd = true 30 | } 31 | } else { 32 | shouldAdd = true 33 | } 34 | if shouldAdd { 35 | mtd.params.append(methodParam) 36 | mtd.pnameId = mtd.pnameId.appending("\(methodParam.name):") 37 | } 38 | 39 | } else if tk == Sb.rBktL { 40 | bracketCount += 1 41 | parsingTf = true 42 | } else if tk == Sb.rBktR { 43 | bracketCount -= 1 44 | if bracketCount == 0 { 45 | var typeString = "" 46 | for typeTk in types { 47 | typeString = typeString.appending(typeTk) 48 | } 49 | if !returnTypeTf { 50 | //完成获取返回 51 | mtd.returnType = typeString 52 | step = 1 53 | returnTypeTf = true 54 | } else { 55 | if step == 2 { 56 | methodParam.type = typeString 57 | step = 3 58 | } 59 | 60 | } 61 | //括弧结束后的重置工作 62 | parsingTf = false 63 | types = [] 64 | } 65 | } else if parsingTf { 66 | types.append(tk) 67 | //todo:返回block类型会使用.设置值的方式,目前获取用过方法方式没有.这种的解析,暂时作为 68 | if tk == Sb.upArrow { 69 | mtd.returnTypeBlockTf = true 70 | } 71 | } else if tk == Sb.colon { 72 | step = 2 73 | } else if step == 1 { 74 | if tk == "initWithCoordinate" { 75 | // 76 | } 77 | methodParam.name = tk 78 | step = 0 79 | } else if step == 3 { 80 | methodParam.iName = tk 81 | step = 1 82 | mtd.params.append(methodParam) 83 | mtd.pnameId = mtd.pnameId.appending("\(methodParam.name):") 84 | methodParam = MethodParam() 85 | } else if tk != Sb.minus && tk != Sb.add { 86 | methodParam.name = tk 87 | } 88 | 89 | }//遍历 90 | 91 | return mtd 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/Producer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Producer.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 2/20/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | class Producer : Observable { 10 | override init() { 11 | super.init() 12 | } 13 | 14 | override func subscribe(_ observer: O) -> Disposable where O.E == Element { 15 | if !CurrentThreadScheduler.isScheduleRequired { 16 | // The returned disposable needs to release all references once it was disposed. 17 | let disposer = SinkDisposer() 18 | let sinkAndSubscription = run(observer, cancel: disposer) 19 | disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription) 20 | 21 | return disposer 22 | } 23 | else { 24 | return CurrentThreadScheduler.instance.schedule(()) { _ in 25 | let disposer = SinkDisposer() 26 | let sinkAndSubscription = self.run(observer, cancel: disposer) 27 | disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription) 28 | 29 | return disposer 30 | } 31 | } 32 | } 33 | 34 | func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 35 | abstractMethod() 36 | } 37 | } 38 | 39 | fileprivate final class SinkDisposer: Cancelable { 40 | fileprivate enum DisposeState: UInt32 { 41 | case disposed = 1 42 | case sinkAndSubscriptionSet = 2 43 | } 44 | 45 | // Jeej, swift API consistency rules 46 | fileprivate enum DisposeStateInt32: Int32 { 47 | case disposed = 1 48 | case sinkAndSubscriptionSet = 2 49 | } 50 | 51 | private var _state: AtomicInt = 0 52 | private var _sink: Disposable? = nil 53 | private var _subscription: Disposable? = nil 54 | 55 | var isDisposed: Bool { 56 | return AtomicFlagSet(DisposeState.disposed.rawValue, &_state) 57 | } 58 | 59 | func setSinkAndSubscription(sink: Disposable, subscription: Disposable) { 60 | _sink = sink 61 | _subscription = subscription 62 | 63 | let previousState = AtomicOr(DisposeState.sinkAndSubscriptionSet.rawValue, &_state) 64 | if (previousState & DisposeStateInt32.sinkAndSubscriptionSet.rawValue) != 0 { 65 | rxFatalError("Sink and subscription were already set") 66 | } 67 | 68 | if (previousState & DisposeStateInt32.disposed.rawValue) != 0 { 69 | sink.dispose() 70 | subscription.dispose() 71 | _sink = nil 72 | _subscription = nil 73 | } 74 | } 75 | 76 | func dispose() { 77 | let previousState = AtomicOr(DisposeState.disposed.rawValue, &_state) 78 | 79 | if (previousState & DisposeStateInt32.disposed.rawValue) != 0 { 80 | return 81 | } 82 | 83 | if (previousState & DisposeStateInt32.sinkAndSubscriptionSet.rawValue) != 0 { 84 | guard let sink = _sink else { 85 | rxFatalError("Sink not set") 86 | } 87 | guard let subscription = _subscription else { 88 | rxFatalError("Subscription not set") 89 | } 90 | 91 | sink.dispose() 92 | subscription.dispose() 93 | 94 | _sink = nil 95 | _subscription = nil 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/ConcurrentMainScheduler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ConcurrentMainScheduler.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 10/17/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | import struct Foundation.Date 10 | import struct Foundation.TimeInterval 11 | import Dispatch 12 | 13 | /** 14 | Abstracts work that needs to be performed on `MainThread`. In case `schedule` methods are called from main thread, it will perform action immediately without scheduling. 15 | 16 | This scheduler is optimized for `subscribeOn` operator. If you want to observe observable sequence elements on main thread using `observeOn` operator, 17 | `MainScheduler` is more suitable for that purpose. 18 | */ 19 | public final class ConcurrentMainScheduler : SchedulerType { 20 | public typealias TimeInterval = Foundation.TimeInterval 21 | public typealias Time = Date 22 | 23 | private let _mainScheduler: MainScheduler 24 | private let _mainQueue: DispatchQueue 25 | 26 | /// - returns: Current time. 27 | public var now : Date { 28 | return _mainScheduler.now as Date 29 | } 30 | 31 | private init(mainScheduler: MainScheduler) { 32 | _mainQueue = DispatchQueue.main 33 | _mainScheduler = mainScheduler 34 | } 35 | 36 | /// Singleton instance of `ConcurrentMainScheduler` 37 | public static let instance = ConcurrentMainScheduler(mainScheduler: MainScheduler.instance) 38 | 39 | /** 40 | Schedules an action to be executed immediatelly. 41 | 42 | - parameter state: State passed to the action to be executed. 43 | - parameter action: Action to be executed. 44 | - returns: The disposable object used to cancel the scheduled action (best effort). 45 | */ 46 | public func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable { 47 | if DispatchQueue.isMain { 48 | return action(state) 49 | } 50 | 51 | let cancel = SingleAssignmentDisposable() 52 | 53 | _mainQueue.async { 54 | if cancel.isDisposed { 55 | return 56 | } 57 | 58 | cancel.setDisposable(action(state)) 59 | } 60 | 61 | return cancel 62 | } 63 | 64 | /** 65 | Schedules an action to be executed. 66 | 67 | - parameter state: State passed to the action to be executed. 68 | - parameter dueTime: Relative time after which to execute the action. 69 | - parameter action: Action to be executed. 70 | - returns: The disposable object used to cancel the scheduled action (best effort). 71 | */ 72 | public final func scheduleRelative(_ state: StateType, dueTime: Foundation.TimeInterval, action: @escaping (StateType) -> Disposable) -> Disposable { 73 | return _mainScheduler.scheduleRelative(state, dueTime: dueTime, action: action) 74 | } 75 | 76 | /** 77 | Schedules a periodic piece of work. 78 | 79 | - parameter state: State passed to the action to be executed. 80 | - parameter startAfter: Period after which initial work should be run. 81 | - parameter period: Period for running the work periodically. 82 | - parameter action: Action to be executed. 83 | - returns: The disposable object used to cancel the scheduled action (best effort). 84 | */ 85 | public func schedulePeriodic(_ state: StateType, startAfter: TimeInterval, period: TimeInterval, action: @escaping (StateType) -> StateType) -> Disposable { 86 | return _mainScheduler.schedulePeriodic(state, startAfter: startAfter, period: period, action: action) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /smck/Lib/RxSwift/TakeUntil.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TakeUntil.swift 3 | // RxSwift 4 | // 5 | // Created by Krunoslav Zaher on 6/7/15. 6 | // Copyright © 2015 Krunoslav Zaher. All rights reserved. 7 | // 8 | 9 | final class TakeUntilSinkOther 10 | : ObserverType 11 | , LockOwnerType 12 | , SynchronizedOnType { 13 | typealias Parent = TakeUntilSink 14 | typealias E = Other 15 | 16 | fileprivate let _parent: Parent 17 | 18 | var _lock: RecursiveLock { 19 | return _parent._lock 20 | } 21 | 22 | fileprivate let _subscription = SingleAssignmentDisposable() 23 | 24 | init(parent: Parent) { 25 | _parent = parent 26 | #if TRACE_RESOURCES 27 | let _ = Resources.incrementTotal() 28 | #endif 29 | } 30 | 31 | func on(_ event: Event) { 32 | synchronizedOn(event) 33 | } 34 | 35 | func _synchronized_on(_ event: Event) { 36 | switch event { 37 | case .next: 38 | _parent.forwardOn(.completed) 39 | _parent.dispose() 40 | case .error(let e): 41 | _parent.forwardOn(.error(e)) 42 | _parent.dispose() 43 | case .completed: 44 | _parent._open = true 45 | _subscription.dispose() 46 | } 47 | } 48 | 49 | #if TRACE_RESOURCES 50 | deinit { 51 | let _ = Resources.decrementTotal() 52 | } 53 | #endif 54 | } 55 | 56 | final class TakeUntilSink 57 | : Sink 58 | , LockOwnerType 59 | , ObserverType 60 | , SynchronizedOnType { 61 | typealias E = O.E 62 | typealias Parent = TakeUntil 63 | 64 | fileprivate let _parent: Parent 65 | 66 | let _lock = RecursiveLock() 67 | 68 | // state 69 | fileprivate var _open = false 70 | 71 | init(parent: Parent, observer: O, cancel: Cancelable) { 72 | _parent = parent 73 | super.init(observer: observer, cancel: cancel) 74 | } 75 | 76 | func on(_ event: Event) { 77 | synchronizedOn(event) 78 | } 79 | 80 | func _synchronized_on(_ event: Event) { 81 | switch event { 82 | case .next: 83 | forwardOn(event) 84 | case .error: 85 | forwardOn(event) 86 | dispose() 87 | case .completed: 88 | forwardOn(event) 89 | dispose() 90 | } 91 | } 92 | 93 | func run() -> Disposable { 94 | let otherObserver = TakeUntilSinkOther(parent: self) 95 | let otherSubscription = _parent._other.subscribe(otherObserver) 96 | otherObserver._subscription.setDisposable(otherSubscription) 97 | let sourceSubscription = _parent._source.subscribe(self) 98 | 99 | return Disposables.create(sourceSubscription, otherObserver._subscription) 100 | } 101 | } 102 | 103 | final class TakeUntil: Producer { 104 | 105 | fileprivate let _source: Observable 106 | fileprivate let _other: Observable 107 | 108 | init(source: Observable, other: Observable) { 109 | _source = source 110 | _other = other 111 | } 112 | 113 | override func run(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element { 114 | let sink = TakeUntilSink(parent: self, observer: observer, cancel: cancel) 115 | let subscription = sink.run() 116 | return (sink: sink, subscription: subscription) 117 | } 118 | } 119 | --------------------------------------------------------------------------------