Skip to content

Commit

Permalink
Add option to exclude classes and/or protocols from mock generation
Browse files Browse the repository at this point in the history
  • Loading branch information
nxtstep committed Apr 25, 2017
1 parent e2e7928 commit 8d09211
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
31 changes: 25 additions & 6 deletions Generator/Source/cuckoo_generator/GenerateMocksCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import SourceKittenFramework
import FileKit
import CuckooGeneratorFramework

private func curry<P1, P2, P3, P4, P5, P6, P7, P8, R>(_ f: @escaping (P1, P2, P3, P4, P5, P6, P7, P8) -> R)
-> (P1) -> (P2) -> (P3) -> (P4) -> (P5) -> (P6) -> (P7) -> (P8) -> R {
return { p1 in { p2 in { p3 in { p4 in { p5 in { p6 in { p7 in { p8 in f(p1, p2, p3, p4, p5, p6, p7, p8) } } } } } } } }
private func curry<P1, P2, P3, P4, P5, P6, P7, P8, P9, R>(_ f: @escaping (P1, P2, P3, P4, P5, P6, P7, P8, P9) -> R)
-> (P1) -> (P2) -> (P3) -> (P4) -> (P5) -> (P6) -> (P7) -> (P8) -> (P9) -> R {
return { p1 in { p2 in { p3 in { p4 in { p5 in { p6 in { p7 in { p8 in { p9 in f(p1, p2, p3, p4, p5, p6, p7, p8, p9) } } } } } } } } }
}

public struct GenerateMocksCommand: CommandProtocol {
Expand All @@ -27,7 +27,9 @@ public struct GenerateMocksCommand: CommandProtocol {
let inputFiles = inputPathValues.map { File(path: $0) }
let tokens = inputFiles.flatMap { $0 }.map { Tokenizer(sourceFile: $0).tokenize() }
let tokensWithInheritance = options.noInheritance ? tokens : mergeInheritance(tokens)
let parsedFiles = options.noClassMocking ? removeClasses(tokensWithInheritance) : tokensWithInheritance
let tokensWithoutClasses = options.noClassMocking ? removeClasses(tokensWithInheritance) : tokensWithInheritance
// filter excluded classes/protocols
let parsedFiles = removeClassesAndProtocols(from: tokensWithoutClasses, in: options.exclude)

let headers = parsedFiles.map { options.noHeader ? "" : FileHeaderHandler.getHeader(of: $0, includeTimestamp: !options.noTimestamp) }
let imports = parsedFiles.map { FileHeaderHandler.getImports(of: $0, testableFrameworks: options.testableFrameworks) }
Expand Down Expand Up @@ -68,6 +70,19 @@ public struct GenerateMocksCommand: CommandProtocol {
return FileRepresentation(sourceFile: $0.sourceFile, declarations: declarations)
}.filter { !$0.declarations.isEmpty }
}

private func removeClassesAndProtocols(from files: [FileRepresentation], in excluded: [String]) -> [FileRepresentation] {
return files.map {
FileRepresentation(sourceFile: $0.sourceFile, declarations: $0.declarations.filter { token in
guard let token = token as? ContainerToken else {
return true
}
return !excluded.contains(token.name)
})
}.filter {
!$0.declarations.isEmpty
}
}

public struct Options: OptionsProtocol {
let files: [String]
Expand All @@ -76,12 +91,14 @@ public struct GenerateMocksCommand: CommandProtocol {
let noTimestamp: Bool
let noInheritance: Bool
let testableFrameworks: [String]
let exclude: [String]
let filePrefix: String
let noClassMocking: Bool

public init(output: String, testableFrameworks: String, noHeader: Bool, noTimestamp: Bool, noInheritance: Bool, filePrefix: String, noClassMocking: Bool, files: [String]) {
public init(output: String, testableFrameworks: String, exclude: String, noHeader: Bool, noTimestamp: Bool, noInheritance: Bool, filePrefix: String, noClassMocking: Bool, files: [String]) {
self.output = output
self.testableFrameworks = testableFrameworks.components(separatedBy: ",").filter { !$0.isEmpty }
self.exclude = exclude.components(separatedBy: ",").filter { !$0.isEmpty }.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
self.noHeader = noHeader
self.noTimestamp = noTimestamp
self.noInheritance = noInheritance
Expand All @@ -94,6 +111,8 @@ public struct GenerateMocksCommand: CommandProtocol {
let output: Result<String, CommandantError<ClientError>> = m <| Option(key: "output", defaultValue: "GeneratedMocks.swift", usage: "Where to put the generated mocks.\nIf a path to a directory is supplied, each input file will have a respective output file with mocks.\nIf a path to a Swift file is supplied, all mocks will be in a single file.\nDefault value is `GeneratedMocks.swift`.")

let testable: Result<String, CommandantError<ClientError>> = m <| Option(key: "testable", defaultValue: "", usage: "A comma separated list of frameworks that should be imported as @testable in the mock files.")

let exclude: Result<String, CommandantError<ClientError>> = m <| Option(key: "exclude", defaultValue: "", usage: "A comma separated list of classes and protocols that should be skipped during mock generation.")

let noHeader: Result<Bool, CommandantError<ClientError>> = m <| Option(key: "no-header", defaultValue: false, usage: "Do not generate file headers.")

Expand All @@ -110,13 +129,13 @@ public struct GenerateMocksCommand: CommandProtocol {
return curry(Options.init)
<*> output
<*> testable
<*> exclude
<*> noHeader
<*> noTimestamp
<*> noInheritance
<*> filePrefix
<*> noClassMocking
<*> input

}
}
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@ Default value is `GeneratedMocks.swift`.

A comma separated list of frameworks that should be imported as @testable in the mock files.

##### `--exclude` (string)

A comma separated list of classes and protocols that should be skipped during mock generation.

##### `--no-header`

Do not generate file headers.
Expand Down

0 comments on commit 8d09211

Please sign in to comment.