Skip to content

Commit

Permalink
Add the option to enable/disable the main thread checker from the gen…
Browse files Browse the repository at this point in the history
…erated schemes (#1382)

* Update the models in ProjectDescription to add support for enabling the main thread checker

* Set disableMainThreadChecker depending on the given diagnostic options

* Fix tests

* Add unit tests

* Update documentation

* Update CHANGELOG

Co-authored-by: Pedro Piñera <pedro@ppinera.es>
  • Loading branch information
Pedro Piñera Buendía and Pedro Piñera committed May 27, 2020
1 parent cd60082 commit dac7cb4
Show file tree
Hide file tree
Showing 18 changed files with 229 additions and 64 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/

- Support for enabling the cloud insights feature [#1335](https://github.com/tuist/tuist/pull/1335) by [@pepibumur](https://github.com/pepibumur)
- Value graph model [#1336](https://github.com/tuist/tuist/pull/1336) by [@pepibumur](https://github.com/pepibumur)
- **Breaking** Support for setting diagnostics options to the test and run actions [#1382](https://github.com/tuist/tuist/pull/1382) by [@pepibumur](https://github.com/pepibumur)

### Fixed

Expand Down
31 changes: 28 additions & 3 deletions Sources/ProjectDescription/RunAction.swift
@@ -1,23 +1,48 @@
import Foundation

/// It represents the test action of a scheme.
public struct RunAction: Equatable, Codable {
/// Name of the configuration that should be used for building the runnable targets.
public let configurationName: String

/// Executable that will be run.
public let executable: TargetReference?

/// Arguments passed to the process running the app.
public let arguments: Arguments?

/// Diagnostics options.
public let diagnosticsOptions: [SchemeDiagnosticsOption]

/// Initializes a new instance of a run action.
/// - Parameters:
/// - configurationName: Name of the configuration that should be used for building the runnable targets.
/// - executable: Executable that will be run.
/// - arguments: Arguments passed to the process running the app.
/// - diagnosticsOptions: Diagnostics options.
public init(configurationName: String,
executable: TargetReference? = nil,
arguments: Arguments? = nil) {
arguments: Arguments? = nil,
diagnosticsOptions: [SchemeDiagnosticsOption] = []) {
self.configurationName = configurationName
self.executable = executable
self.arguments = arguments
self.diagnosticsOptions = diagnosticsOptions
}

/// Initializes a new instance of a run action.
/// - Parameters:
/// - config: Configuration that should be used for building the test targets.
/// - executable: Executable that will be run.
/// - arguments: Arguments passed to the process running the app.
/// - diagnosticsOptions: Diagnostics options.
public init(config: PresetBuildConfiguration = .debug,
executable: TargetReference? = nil,
arguments: Arguments? = nil) {
arguments: Arguments? = nil,
diagnosticsOptions: [SchemeDiagnosticsOption] = []) {
self.init(configurationName: config.name,
executable: executable,
arguments: arguments)
arguments: arguments,
diagnosticsOptions: diagnosticsOptions)
}
}
6 changes: 6 additions & 0 deletions Sources/ProjectDescription/SchemeDiagnosticsOption.swift
@@ -0,0 +1,6 @@
import Foundation

public enum SchemeDiagnosticsOption: String, Equatable, Codable {
/// Enable the main thread cheker
case mainThreadChecker
}
47 changes: 44 additions & 3 deletions Sources/ProjectDescription/TestAction.swift
@@ -1,43 +1,84 @@
import Foundation

/// It represents the test action of a scheme.
public struct TestAction: Equatable, Codable {
/// List of targets to be tested.
public let targets: [TestableTarget]

/// Arguments passed to the process running the tests.
public let arguments: Arguments?

/// Name of the configuration that should be used for building the test targets.
public let configurationName: String

/// True to collect the test coverage results.
public let coverage: Bool

/// List of targets for which Xcode will collect the coverage results.
public let codeCoverageTargets: [TargetReference]

/// List of actions to be executed before running the tests.
public let preActions: [ExecutionAction]

/// List of actions to be executed after running the tests.
public let postActions: [ExecutionAction]

/// Diagnostics options.
public let diagnosticsOptions: [SchemeDiagnosticsOption]

/// Initializes a new instance of a test action
/// - Parameters:
/// - targets: List of targets to be tested.
/// - arguments: Arguments passed to the process running the tests.
/// - configurationName: Name of the configuration that should be used for building the test targets.
/// - coverage: True to collect the test coverage results.
/// - codeCoverageTargets: List of targets for which Xcode will collect the coverage results.
/// - preActions: ist of actions to be executed before running the tests.
/// - postActions: List of actions to be executed after running the tests.
/// - diagnosticsOptions: Diagnostics options.
public init(targets: [TestableTarget] = [],
arguments: Arguments? = nil,
configurationName: String,
coverage: Bool = false,
codeCoverageTargets: [TargetReference] = [],
preActions: [ExecutionAction] = [],
postActions: [ExecutionAction] = []) {
postActions: [ExecutionAction] = [],
diagnosticsOptions: [SchemeDiagnosticsOption] = []) {
self.targets = targets
self.arguments = arguments
self.configurationName = configurationName
self.coverage = coverage
self.preActions = preActions
self.postActions = postActions
self.codeCoverageTargets = codeCoverageTargets
self.diagnosticsOptions = diagnosticsOptions
}

/// Initializes a new instance of a test action
/// - Parameters:
/// - targets: List of targets to be tested.
/// - arguments: Arguments passed to the process running the tests.
/// - config: Configuration that should be used for building the test targets.
/// - coverage: True to collect the test coverage results.
/// - codeCoverageTargets: List of targets for which Xcode will collect the coverage results.
/// - preActions: ist of actions to be executed before running the tests.
/// - postActions: List of actions to be executed after running the tests.
/// - diagnosticsOptions: Diagnostics options.
public init(targets: [TestableTarget],
arguments: Arguments? = nil,
config: PresetBuildConfiguration = .debug,
coverage: Bool = false,
codeCoverageTargets: [TargetReference] = [],
preActions: [ExecutionAction] = [],
postActions: [ExecutionAction] = []) {
postActions: [ExecutionAction] = [],
diagnosticsOptions: [SchemeDiagnosticsOption] = []) {
self.init(targets: targets,
arguments: arguments,
configurationName: config.name,
coverage: coverage,
codeCoverageTargets: codeCoverageTargets,
preActions: preActions,
postActions: postActions)
postActions: postActions,
diagnosticsOptions: diagnosticsOptions)
}
}
9 changes: 6 additions & 3 deletions Sources/TuistCore/Models/RunAction.swift
Expand Up @@ -8,16 +8,19 @@ public struct RunAction: Equatable {
public let executable: TargetReference?
public let filePath: AbsolutePath?
public let arguments: Arguments?
public let diagnosticsOptions: Set<SchemeDiagnosticsOption>

// MARK: - Init

public init(configurationName: String,
executable: TargetReference? = nil,
filePath: AbsolutePath? = nil,
arguments: Arguments? = nil) {
executable: TargetReference?,
filePath: AbsolutePath?,
arguments: Arguments?,
diagnosticsOptions: Set<SchemeDiagnosticsOption>) {
self.configurationName = configurationName
self.executable = executable
self.filePath = filePath
self.arguments = arguments
self.diagnosticsOptions = diagnosticsOptions
}
}
5 changes: 5 additions & 0 deletions Sources/TuistCore/Models/SchemeDiagnosticsOption.swift
@@ -0,0 +1,5 @@
import Foundation

public enum SchemeDiagnosticsOption: Equatable {
case mainThreadChecker
}
15 changes: 9 additions & 6 deletions Sources/TuistCore/Models/TestAction.swift
Expand Up @@ -11,22 +11,25 @@ public struct TestAction: Equatable {
public let codeCoverageTargets: [TargetReference]
public let preActions: [ExecutionAction]
public let postActions: [ExecutionAction]
public let diagnosticsOptions: Set<SchemeDiagnosticsOption>

// MARK: - Init

public init(targets: [TestableTarget] = [],
arguments: Arguments? = nil,
public init(targets: [TestableTarget],
arguments: Arguments?,
configurationName: String,
coverage: Bool = false,
codeCoverageTargets: [TargetReference] = [],
preActions: [ExecutionAction] = [],
postActions: [ExecutionAction] = []) {
coverage: Bool,
codeCoverageTargets: [TargetReference],
preActions: [ExecutionAction],
postActions: [ExecutionAction],
diagnosticsOptions: Set<SchemeDiagnosticsOption>) {
self.targets = targets
self.arguments = arguments
self.configurationName = configurationName
self.coverage = coverage
self.preActions = preActions
self.postActions = postActions
self.codeCoverageTargets = codeCoverageTargets
self.diagnosticsOptions = diagnosticsOptions
}
}
6 changes: 4 additions & 2 deletions Sources/TuistCoreTesting/Models/RunAction+TestData.swift
Expand Up @@ -6,10 +6,12 @@ public extension RunAction {
static func test(configurationName: String = BuildConfiguration.debug.name,
executable: TargetReference? = TargetReference(projectPath: "/Project", name: "App"),
filePath: AbsolutePath? = nil,
arguments: Arguments? = Arguments.test()) -> RunAction {
arguments: Arguments? = Arguments.test(),
diagnosticsOptions: Set<SchemeDiagnosticsOption> = Set()) -> RunAction {
RunAction(configurationName: configurationName,
executable: executable,
filePath: filePath,
arguments: arguments)
arguments: arguments,
diagnosticsOptions: diagnosticsOptions)
}
}
6 changes: 4 additions & 2 deletions Sources/TuistCoreTesting/Models/TestAction+TestData.swift
Expand Up @@ -9,13 +9,15 @@ public extension TestAction {
coverage: Bool = false,
codeCoverageTargets: [TargetReference] = [],
preActions: [ExecutionAction] = [],
postActions: [ExecutionAction] = []) -> TestAction {
postActions: [ExecutionAction] = [],
diagnosticsOptions: Set<SchemeDiagnosticsOption> = Set()) -> TestAction {
TestAction(targets: targets,
arguments: arguments,
configurationName: configurationName,
coverage: coverage,
codeCoverageTargets: codeCoverageTargets,
preActions: preActions,
postActions: postActions)
postActions: postActions,
diagnosticsOptions: diagnosticsOptions)
}
}
18 changes: 16 additions & 2 deletions Sources/TuistGenerator/Generator/SchemesGenerator.swift
Expand Up @@ -110,10 +110,19 @@ final class SchemesGenerator: SchemesGenerating {
return Scheme(name: target.name,
shared: true,
buildAction: BuildAction(targets: [targetReference]),
testAction: TestAction(targets: testTargets, configurationName: buildConfiguration),
testAction: TestAction(targets: testTargets,
arguments: nil,
configurationName: buildConfiguration,
coverage: false,
codeCoverageTargets: [],
preActions: [],
postActions: [],
diagnosticsOptions: Set()),
runAction: RunAction(configurationName: buildConfiguration,
executable: targetReference,
arguments: Arguments(environment: target.environment)))
filePath: nil,
arguments: Arguments(environment: target.environment),
diagnosticsOptions: Set()))
}

/// Generate schemes for a project or workspace.
Expand Down Expand Up @@ -269,6 +278,7 @@ final class SchemesGenerator: SchemesGenerating {

let onlyGenerateCoverageForSpecifiedTargets = codeCoverageTargets.count > 0 ? true : nil

let disableMainThreadChecker = !testAction.diagnosticsOptions.contains(.mainThreadChecker)
let shouldUseLaunchSchemeArgsEnv: Bool = args == nil && environments == nil

return XCScheme.TestAction(buildConfiguration: testAction.configurationName,
Expand All @@ -280,6 +290,7 @@ final class SchemesGenerator: SchemesGenerating {
codeCoverageEnabled: testAction.coverage,
codeCoverageTargets: codeCoverageTargets,
onlyGenerateCoverageForSpecifiedTargets: onlyGenerateCoverageForSpecifiedTargets,
disableMainThreadChecker: disableMainThreadChecker,
commandlineArguments: args,
environmentVariables: environments)
}
Expand Down Expand Up @@ -333,10 +344,13 @@ final class SchemesGenerator: SchemesGenerating {
}

let buildConfiguration = scheme.runAction?.configurationName ?? defaultBuildConfiguration
let disableMainThreadChecker = scheme.runAction?.diagnosticsOptions.contains(.mainThreadChecker) == false

return XCScheme.LaunchAction(runnable: buildableProductRunnable,
buildConfiguration: buildConfiguration,
macroExpansion: macroExpansion,
pathRunnable: pathRunnable,
disableMainThreadChecker: disableMainThreadChecker,
commandlineArguments: commandlineArguments,
environmentVariables: environments)
}
Expand Down
3 changes: 1 addition & 2 deletions Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift
Expand Up @@ -72,8 +72,7 @@ final class ProjectEditorMapper: ProjectEditorMapping {
// Run Scheme
let buildAction = BuildAction(targets: targets.map { TargetReference(projectPath: sourceRootPath, name: $0.name) })
let arguments = Arguments(launch: ["generate --path \(sourceRootPath)": true])

let runAction = RunAction(configurationName: "Debug", filePath: tuistPath, arguments: arguments)
let runAction = RunAction(configurationName: "Debug", executable: nil, filePath: tuistPath, arguments: arguments, diagnosticsOptions: Set())
let scheme = Scheme(name: "Manifests", shared: true, buildAction: buildAction, runAction: runAction)

// Project
Expand Down
Expand Up @@ -18,9 +18,11 @@ extension TuistCore.RunAction {
executableResolved = TargetReference(projectPath: try generatorPaths.resolveSchemeActionProjectPath(executable.projectPath),
name: executable.targetName)
}

return RunAction(configurationName: configurationName,
executable: executableResolved,
arguments: arguments)
let diagnosticsOptions = Set(manifest.diagnosticsOptions.map { TuistCore.SchemeDiagnosticsOption.from(manifest: $0) })
return TuistCore.RunAction(configurationName: configurationName,
executable: executableResolved,
filePath: nil,
arguments: arguments,
diagnosticsOptions: diagnosticsOptions)
}
}
@@ -0,0 +1,12 @@
import Foundation
import ProjectDescription
import TSCBasic
import TuistCore

extension TuistCore.SchemeDiagnosticsOption {
static func from(manifest: ProjectDescription.SchemeDiagnosticsOption) -> TuistCore.SchemeDiagnosticsOption {
switch manifest {
case .mainThreadChecker: return .mainThreadChecker
}
}
}
Expand Up @@ -21,13 +21,15 @@ extension TuistCore.TestAction {
generatorPaths: generatorPaths) }
let postActions = try manifest.postActions.map { try TuistCore.ExecutionAction.from(manifest: $0,
generatorPaths: generatorPaths) }
let diagnosticsOptions = Set(manifest.diagnosticsOptions.map { TuistCore.SchemeDiagnosticsOption.from(manifest: $0) })

return TestAction(targets: targets,
arguments: arguments,
configurationName: configurationName,
coverage: coverage,
codeCoverageTargets: codeCoverageTargets,
preActions: preActions,
postActions: postActions)
postActions: postActions,
diagnosticsOptions: diagnosticsOptions)
}
}
Expand Up @@ -460,7 +460,9 @@ final class SchemesGeneratorTests: XCTestCase {
let target = Target.test(name: "Library", platform: .iOS, product: .dynamicLibrary)

let buildAction = BuildAction.test(targets: [TargetReference(projectPath: projectPath, name: "Library")])
let launchAction = RunAction.test(configurationName: "Debug", filePath: "/usr/bin/foo")
let launchAction = RunAction.test(configurationName: "Debug",
filePath: "/usr/bin/foo",
diagnosticsOptions: Set(arrayLiteral: .mainThreadChecker))

let scheme = Scheme.test(name: "Library", buildAction: buildAction, runAction: launchAction)
let project = Project.test(path: projectPath, targets: [target])
Expand All @@ -477,6 +479,7 @@ final class SchemesGeneratorTests: XCTestCase {
XCTAssertNil(result.runnable?.buildableReference)
XCTAssertEqual(result.buildConfiguration, "Debug")
XCTAssertEqual(result.pathRunnable?.filePath, "/usr/bin/foo")
XCTAssertFalse(result.disableMainThreadChecker)
}

func test_schemeLaunchAction_with_path() throws {
Expand All @@ -485,7 +488,8 @@ final class SchemesGeneratorTests: XCTestCase {
let target = Target.test(name: "Library", platform: .iOS, product: .dynamicLibrary)

let buildAction = BuildAction.test(targets: [TargetReference(projectPath: projectPath, name: "Library")])
let testAction = TestAction.test(targets: [TestableTarget(target: TargetReference(projectPath: projectPath, name: "Library"))])
let testAction = TestAction.test(targets: [TestableTarget(target: TargetReference(projectPath: projectPath, name: "Library"))],
diagnosticsOptions: Set(arrayLiteral: .mainThreadChecker))

let scheme = Scheme.test(name: "Library", buildAction: buildAction, testAction: testAction, runAction: nil)
let project = Project.test(path: projectPath, targets: [target])
Expand All @@ -506,6 +510,7 @@ final class SchemesGeneratorTests: XCTestCase {
XCTAssertEqual(result.macroExpansion?.buildableName, "libLibrary.dylib")
XCTAssertEqual(result.macroExpansion?.blueprintName, "Library")
XCTAssertEqual(result.macroExpansion?.buildableIdentifier, "primary")
XCTAssertFalse(result.disableMainThreadChecker)
}

// MARK: - Profile Action Tests
Expand Down

0 comments on commit dac7cb4

Please sign in to comment.