Skip to content

Commit

Permalink
Improved error logging
Browse files Browse the repository at this point in the history
Fixed an issue when the compiler could wrap a context in to double optional in the complicated configurations.
  • Loading branch information
ekazaev committed Apr 17, 2019
1 parent 3c29ca9 commit 35106ca
Show file tree
Hide file tree
Showing 295 changed files with 3,012 additions and 1,008 deletions.
6 changes: 3 additions & 3 deletions Example/Tests/AssemblyTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AssemblyTest: XCTestCase {
while currentStep != nil {
chainedStepCount += 1
if let chainableStep = currentStep as? ChainableStep {
currentStep = chainableStep.getPreviousStep(with: nil)
currentStep = chainableStep.getPreviousStep(with: nil as Any?)
} else {
currentStep = nil
}
Expand All @@ -43,7 +43,7 @@ class AssemblyTest: XCTestCase {
while currentStep != nil {
chainedStepCount += 1
if let chainableStep = currentStep as? ChainableStep {
currentStep = chainableStep.getPreviousStep(with: nil)
currentStep = chainableStep.getPreviousStep(with: nil as Any?)
} else {
currentStep = nil
}
Expand All @@ -62,7 +62,7 @@ class AssemblyTest: XCTestCase {
while currentStep != nil {
chainedStepCount += 1
if let chainableStep = currentStep as? ChainableStep {
currentStep = chainableStep.getPreviousStep(with: nil)
currentStep = chainableStep.getPreviousStep(with: nil as Any?)
} else {
currentStep = nil
}
Expand Down
2 changes: 1 addition & 1 deletion Example/Tests/BoxTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class BoxTests: XCTestCase {
.using(ViewControllerActions.NilAction())
.from(GeneralStep.current())
.assemble()
let step = routingStep.getPreviousStep(with: nil) as? BaseStep
let step = routingStep.getPreviousStep(with: nil as Any?) as? BaseStep
XCTAssertNotNil(step)
XCTAssertNil(step?.factory)
XCTAssertNil(step?.finder)
Expand Down
28 changes: 14 additions & 14 deletions Example/Tests/DestinationStepTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ class DestinationStepTests: XCTestCase {
// Will compile but will not work in runtime.
let _: DestinationStep<UITabBarController, Any?> = nonContainerStepInsideContainer.expectingContainer()

XCTAssertNoThrow(try (step.getPreviousStep(with: nil) as? PerformableStep)?.perform(with: nil))
XCTAssertNoThrow(try (step.getPreviousStep(with: nil) as? PerformableStep)?.perform(with: "nil"))
XCTAssertNoThrow(try (step.getPreviousStep(with: nil) as? PerformableStep)?.perform(with: ()))
XCTAssertNoThrow(try (step.getPreviousStep(with: nil as Any?) as? PerformableStep)?.perform(with: nil as Any?))
XCTAssertNoThrow(try (step.getPreviousStep(with: nil as Any?) as? PerformableStep)?.perform(with: "nil"))
XCTAssertNoThrow(try (step.getPreviousStep(with: nil as Any?) as? PerformableStep)?.perform(with: ()))
}

func testStronglyTypedExpectingContainer() {
Expand All @@ -53,7 +53,7 @@ class DestinationStepTests: XCTestCase {
let _: DestinationStep<UITabBarController, String> = nonContainerStepInsideContainer.expectingContainer()

XCTAssertNoThrow(try (step.getPreviousStep(with: "") as? PerformableStep)?.perform(with: "nil"))
XCTAssertThrowsError(try (step.getPreviousStep(with: "") as? PerformableStep)?.perform(with: nil))
XCTAssertThrowsError(try (step.getPreviousStep(with: "") as? PerformableStep)?.perform(with: nil as Any?))
XCTAssertThrowsError(try (step.getPreviousStep(with: "") as? PerformableStep)?.perform(with: ()))
}

Expand All @@ -64,12 +64,12 @@ class DestinationStepTests: XCTestCase {

let step1: DestinationStep<UINavigationController, String> = nonContainerStepInsideContainer.adaptingContext()
let step2: DestinationStep<UINavigationController, Void> = nonContainerStepInsideContainer.adaptingContext()
XCTAssertNoThrow(try (step1.getPreviousStep(with: nil) as? PerformableStep)?.perform(with: nil))
XCTAssertNoThrow(try (step2.getPreviousStep(with: nil) as? PerformableStep)?.perform(with: nil))
XCTAssertNoThrow(try (step1.getPreviousStep(with: nil) as? PerformableStep)?.perform(with: "nil"))
XCTAssertNoThrow(try (step2.getPreviousStep(with: nil) as? PerformableStep)?.perform(with: "nil"))
XCTAssertNoThrow(try (step1.getPreviousStep(with: nil) as? PerformableStep)?.perform(with: ()))
XCTAssertNoThrow(try (step2.getPreviousStep(with: nil) as? PerformableStep)?.perform(with: ()))
XCTAssertNoThrow(try (step1.getPreviousStep(with: nil as Any?) as? PerformableStep)?.perform(with: nil as Any?))
XCTAssertNoThrow(try (step2.getPreviousStep(with: nil as Any?) as? PerformableStep)?.perform(with: nil as Any?))
XCTAssertNoThrow(try (step1.getPreviousStep(with: nil as Any?) as? PerformableStep)?.perform(with: "nil"))
XCTAssertNoThrow(try (step2.getPreviousStep(with: nil as Any?) as? PerformableStep)?.perform(with: "nil"))
XCTAssertNoThrow(try (step1.getPreviousStep(with: nil as Any?) as? PerformableStep)?.perform(with: ()))
XCTAssertNoThrow(try (step2.getPreviousStep(with: nil as Any?) as? PerformableStep)?.perform(with: ()))
}

func testSingleUniversalExpectingContainer() {
Expand All @@ -84,7 +84,7 @@ class DestinationStepTests: XCTestCase {
// Will compile but will not work in runtime.
let _: ActionToStepIntegrator<UITabBarController, Any?> = nonContainerStepInsideContainer.expectingContainer()

XCTAssertNoThrow(try (step.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: nil))
XCTAssertNoThrow(try (step.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: nil as Any?))
XCTAssertNoThrow(try (step.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: "nil"))
XCTAssertNoThrow(try (step.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: ()))
}
Expand All @@ -103,7 +103,7 @@ class DestinationStepTests: XCTestCase {
// Will compile but will not work in runtime.
let _: ActionToStepIntegrator<UITabBarController, String> = nonContainerStepInsideContainer.expectingContainer()

XCTAssertThrowsError(try (step.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: nil))
XCTAssertThrowsError(try (step.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: nil as Any?))
XCTAssertNoThrow(try (step.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: "nil"))
XCTAssertThrowsError(try (step.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: ()))
}
Expand All @@ -113,8 +113,8 @@ class DestinationStepTests: XCTestCase {

let step1: ActionToStepIntegrator<UINavigationController, String> = nonContainerStepInsideContainer.adaptingContext()
let step2: ActionToStepIntegrator<UINavigationController, Void> = nonContainerStepInsideContainer.adaptingContext()
XCTAssertNoThrow(try (step1.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: nil))
XCTAssertNoThrow(try (step2.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: nil))
XCTAssertNoThrow(try (step1.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: nil as Any?))
XCTAssertNoThrow(try (step2.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: nil as Any?))
XCTAssertNoThrow(try (step1.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: "nil"))
XCTAssertNoThrow(try (step2.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: "nil"))
XCTAssertNoThrow(try (step1.routingStep(with: ViewControllerActions.NilAction()) as? PerformableStep)?.perform(with: ()))
Expand Down
8 changes: 8 additions & 0 deletions Example/Tests/ErrorTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ class ErrorTests: XCTestCase {
context = RoutingError.Context("Test description")
error = RoutingError.compositionFailed(context)
XCTAssertEqual(error.description, "Composition Failed Error: Test description")

context = RoutingError.Context("Test description")
error = RoutingError.initialController(.notFound, context)
XCTAssertEqual(error.description, "Initial Controller Error (Initial controller not found): Test description")

context = RoutingError.Context("Test description")
error = RoutingError.initialController(.deallocated, context)
XCTAssertEqual(error.description, "Initial Controller Error (Initial controller deallocated): Test description")
}

func testContextDescription() {
Expand Down
14 changes: 7 additions & 7 deletions Example/Tests/MultiplexerTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class MultiplexerTest: XCTestCase {
]

var multiplexer = InterceptorMultiplexer(interceptors)
try? multiplexer.prepare(with: nil)
try? multiplexer.prepare(with: nil as Any?)
XCTAssertEqual(prepareCountRun, 10)
}

Expand All @@ -43,7 +43,7 @@ class MultiplexerTest: XCTestCase {
]

var multiplexer = InterceptorMultiplexer(interceptors)
XCTAssertThrowsError(try multiplexer.prepare(with: nil))
XCTAssertThrowsError(try multiplexer.prepare(with: nil as Any?))
}

func testRoutingWrongContextTypeInterceptorThrow() {
Expand Down Expand Up @@ -85,8 +85,8 @@ class MultiplexerTest: XCTestCase {
]

var multiplexer = ContextTaskMultiplexer(contextTask)
try? multiplexer.prepare(with: nil)
try? multiplexer.apply(on: UIViewController(), with: nil)
try? multiplexer.prepare(with: nil as Any?)
try? multiplexer.apply(on: UIViewController(), with: nil as Any?)
}

func testContextTaskWrongContextTypeThrow() {
Expand All @@ -97,7 +97,7 @@ class MultiplexerTest: XCTestCase {
]

let multiplexer = ContextTaskMultiplexer(contextTask)
XCTAssertThrowsError(try multiplexer.apply(on: UIViewController(), with: nil))
XCTAssertThrowsError(try multiplexer.apply(on: UIViewController(), with: nil as Any?))
}

func testPostTaskWrongContextTypeThrow() {
Expand Down Expand Up @@ -128,8 +128,8 @@ class MultiplexerTest: XCTestCase {
}

var multiplexer = InterceptorMultiplexer([RoutingInterceptorBox(Interceptor())])
try? multiplexer.prepare(with: nil)
multiplexer.execute(with: nil) { (result: InterceptorResult) in
try? multiplexer.prepare(with: nil as Any?)
multiplexer.execute(with: nil as Any?) { (result: InterceptorResult) in
guard case .continueRouting = result else {
XCTAssertFalse(true)
return
Expand Down
2 changes: 1 addition & 1 deletion Example/Tests/RouterTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class RouterTests: XCTestCase {
self.currentViewController = currentViewController
}

func perform(with context: Any?) -> PerformableStepResult {
func perform<Context>(with context: Context) -> PerformableStepResult {
return .success(currentViewController)
}

Expand Down
2 changes: 1 addition & 1 deletion RouteComposer.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'RouteComposer'
s.version = '1.5.1'
s.version = '1.5.2'
s.summary = 'Protocol oriented library that helps to handle view controllers composition, navigation and deep linking tasks.'

s.description = <<-DESC
Expand Down
4 changes: 2 additions & 2 deletions RouteComposer/Classes/Assemblies/SwitchAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public final class SwitchAssembly<ViewController: UIViewController, Context> {
self.resolverBlock = resolverBlock
}

func resolve(with context: Any?) -> RoutingStep? {
func resolve<C>(with context: C) -> RoutingStep? {
guard let typedContext = context as? Context else {
return nil
}
Expand All @@ -62,7 +62,7 @@ public final class SwitchAssembly<ViewController: UIViewController, Context> {
self.finder = FinderBox(finder)
}

func resolve(with context: Any?) -> RoutingStep? {
func resolve<Context>(with context: Context) -> RoutingStep? {
guard (try? finder?.findViewController(with: context)) != nil else {
return nil
}
Expand Down
8 changes: 4 additions & 4 deletions RouteComposer/Classes/DestinationStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ public struct DestinationStep<VC: UIViewController, C>: RoutingStep, ChainableSt
/// Type of the `Context` associated with the step
public typealias Context = C

func getPreviousStep(with context: Any?) -> RoutingStep? {
return destinationStep
}

let destinationStep: RoutingStep

init(_ destinationStep: RoutingStep) {
self.destinationStep = destinationStep
}

func getPreviousStep<Context>(with context: Context) -> RoutingStep? {
return destinationStep
}

/// Adapts context and view controller type dependencies.
///
/// *NB:* Developer guaranties that this types will compliment in runtime.
Expand Down
35 changes: 18 additions & 17 deletions RouteComposer/Classes/Router/DefaultRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,16 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
}
}

private func prepareTaskStack(with context: Any?) throws -> GlobalTaskRunner {
let interceptorRunner = try InterceptorRunner(interceptors: self.interceptors, context: context)
let contextTaskRunner = try ContextTaskRunner(contextTasks: self.contextTasks, context: context)
private func prepareTaskStack<Context>(with context: Context) throws -> GlobalTaskRunner {
let interceptorRunner = try InterceptorRunner(interceptors: self.interceptors, with: context)
let contextTaskRunner = try ContextTaskRunner(contextTasks: self.contextTasks, with: context)
let postTaskDelayedRunner = PostTaskDelayedRunner()
let postTaskRunner = PostTaskRunner(postTasks: self.postTasks, context: context, delayedRunner: postTaskDelayedRunner)
let postTaskRunner = PostTaskRunner(postTasks: self.postTasks, with: context, delayedRunner: postTaskDelayedRunner)
return GlobalTaskRunner(interceptorRunner: interceptorRunner, contextTaskRunner: contextTaskRunner, postTaskRunner: postTaskRunner)
}

private func prepareFactoriesStack(to finalStep: RoutingStep, with context: Any?, taskStack: GlobalTaskRunner) throws -> (rootViewController: UIViewController,
factories: [AnyFactory]) {
private func prepareFactoriesStack<Context>(to finalStep: RoutingStep, with context: Context, taskStack: GlobalTaskRunner) throws -> (rootViewController: UIViewController,
factories: [AnyFactory]) {
logger?.log(.info("Started to search for the view controller to start the navigation process from."))

let result = try sequence(first: finalStep, next: { ($0 as? ChainableStep)?.getPreviousStep(with: context) })
Expand All @@ -98,14 +98,14 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
}

// Creates a class responsible to run the tasks for this particular step
let viewControllerTaskRunner = try taskStack.taskRunnerFor(step: step)
let viewControllerTaskRunner = try taskStack.taskRunnerFor(step: step, with: context)

// Performs current step
switch try step.perform(with: context) {
case .success(let viewController):
logger?.log(.info("\(String(describing: step)) found " +
"\(String(describing: viewController)) to start the navigation process from."))
try viewControllerTaskRunner.run(on: viewController)
try viewControllerTaskRunner.run(on: viewController, with: context)
return (rootViewController: viewController, result.factories)
case .build(let originalFactory):
// If the view controller to start from is not found, but the current step has a `Factory` to build it,
Expand Down Expand Up @@ -138,7 +138,7 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {

//Throws an exception if it hasn't found a view controller to start the stack from.
guard let rootViewController = result.rootViewController else {
throw RoutingError.compositionFailed(.init("Unable to start the navigation process as the view controller to start from was not found."))
throw RoutingError.initialController(.notFound, .init("Unable to start the navigation process as the view controller to start from was not found."))
}

return (rootViewController: rootViewController, factories: result.factories)
Expand All @@ -152,7 +152,8 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
completion: @escaping (RoutingResult) -> Void) {
// Executes interceptors associated to each view in the chain. All the interceptors must succeed to
// continue navigation process. This operation is async.
taskStack.executeInterceptors { [weak viewController] result in
let initialControllerDescription = String(describing: viewController)
taskStack.executeInterceptors(with: context) { [weak viewController] result in
self.assertIfNotMainThread(logger: self.logger)

if case let .failure(error) = result {
Expand All @@ -161,7 +162,7 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
}

guard let viewController = viewController else {
completion(.failure(RoutingError.compositionFailed(.init("A view controller that has been chosen as a " +
completion(.failure(RoutingError.initialController(.deallocated, .init("A view controller \(initialControllerDescription) that has been chosen as a " +
"starting point of the navigation process was destroyed while the router was waiting for the interceptors to finish."))))
return
}
Expand All @@ -187,7 +188,7 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
if case let .failure(error) = result {
throw error
}
try taskStack.runPostTasks()
try taskStack.runPostTasks(with: context)
completion(result)
} catch let error {
completion(.failure(error))
Expand All @@ -200,11 +201,11 @@ public struct DefaultRouter: InterceptableRouter, MainThreadChecking {
// Loops through the list of factories and builds their view controllers in sequence.
// Some actions can be asynchronous, like push, modal or presentations,
// so it performs them asynchronously
private func buildViewControllerStack(starting rootViewController: UIViewController,
with context: Any?,
using factories: [AnyFactory],
animated: Bool,
completion: @escaping ((_: UIViewController, _: RoutingResult) -> Void)) {
private func buildViewControllerStack<Context>(starting rootViewController: UIViewController,
with context: Context,
using factories: [AnyFactory],
animated: Bool,
completion: @escaping ((_: UIViewController, _: RoutingResult) -> Void)) {
var factories = factories

let delayedIntegrationHandler = DefaultDelayedIntegrationHandler(logger: logger)
Expand Down
4 changes: 2 additions & 2 deletions RouteComposer/Classes/Router/Internal/BaseStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ struct BaseStep: RoutingStep,
self.postTask = taskProvider.postTask
}

func getPreviousStep(with context: Any?) -> RoutingStep? {
func getPreviousStep<Context>(with context: Context) -> RoutingStep? {
return previousStep
}

func perform(with context: Any?) throws -> PerformableStepResult {
func perform<Context>(with context: Context) throws -> PerformableStepResult {
guard let viewController = try finder?.findViewController(with: context) else {
if let factory = factory {
return .build(factory)
Expand Down
Loading

0 comments on commit 35106ca

Please sign in to comment.