Skip to content

Commit

Permalink
Propagate error to avoid downstream execution
Browse files Browse the repository at this point in the history
As the compilation task does not throw an exception, but rather we model
failures in the DAG, we need to propagate the error down the task
dependency chain so that tasks that depend on compilation do not
continue if compilation has failed.

In this vein, this commit aligns the codebase to behave like this, and
then avoid testing a project that has not correctly compiled.
  • Loading branch information
jvican committed Mar 14, 2018
1 parent 4921792 commit e168ca9
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 19 deletions.
2 changes: 1 addition & 1 deletion frontend/src/main/scala/bloop/cli/ExitStatus.scala
Expand Up @@ -29,7 +29,7 @@ object ExitStatus {
}
}

val Ok, UnexpectedError, ParseError, InvalidCommandLineOption: ExitStatus =
val Ok, UnexpectedError, ParseError, InvalidCommandLineOption, CompilationError, TestExecutionError, RunError: ExitStatus =
generateExitStatus

def apply(code: Int): ExitStatus = {
Expand Down
46 changes: 31 additions & 15 deletions frontend/src/main/scala/bloop/engine/Interpreter.scala
Expand Up @@ -101,9 +101,8 @@ object Interpreter {

state.build.getProjectFor(cmd.project) match {
case Some(project) =>
def doCompile(state: State): Task[State] = {
def doCompile(state: State): Task[State] =
Tasks.compile(state, project, reporterConfig).map(_.mergeStatus(ExitStatus.Ok))
}

val initialState = {
if (cmd.incremental) Task(state)
Expand All @@ -112,6 +111,7 @@ object Interpreter {
Tasks.clean(state, state.build.projects, true)
}
}

initialState.flatMap { state =>
if (!cmd.watch) doCompile(state)
else watch(project, state, doCompile _)
Expand Down Expand Up @@ -139,15 +139,31 @@ object Interpreter {
state.mergeStatus(ExitStatus.Ok)
}

private def compileAnd(
state: State,
project: Project,
reporterConfig: ReporterConfig,
excludeRoot: Boolean
)(next: State => Task[State]): Task[State] = {
Tasks.compile(state, project, reporterConfig, excludeRoot).flatMap { compiled =>
if (compiled.status != ExitStatus.CompilationError) next(compiled)
else {
Task.now {
compiled.logger.debug(s"Failed compilation for ${project}. Skipping tests.")
compiled
}
}
}
}

private def console(cmd: Commands.Console, state: State): Task[State] = {
val reporterConfig = ReporterConfig.toFormat(cmd.reporter)

state.build.getProjectFor(cmd.project) match {
case Some(project) =>
for {
compiled <- Tasks.compile(state, project, reporterConfig, cmd.excludeRoot)
result <- Tasks.console(compiled, project, reporterConfig, cmd.excludeRoot)
} yield result.mergeStatus(ExitStatus.Ok)
compileAnd(state, project, reporterConfig, cmd.excludeRoot) { state =>
Tasks.console(state, project, reporterConfig, cmd.excludeRoot)
}
case None =>
Task(reportMissing(cmd.project :: Nil, state))
}
Expand All @@ -161,10 +177,10 @@ object Interpreter {
def doTest(state: State): Task[State] = {
val testFilter = TestInternals.parseFilters(cmd.filter)
val cwd = cmd.cliOptions.common.workingPath
for {
compiled <- Tasks.compile(state, project, reporterConfig, excludeRoot = false)
result <- Tasks.test(compiled, project, cwd, cmd.isolated, testFilter)
} yield result

compileAnd(state, project, reporterConfig, excludeRoot = false) { state =>
Tasks.test(state, project, cwd, cmd.isolated, testFilter)
}
}
if (cmd.watch) watch(project, state, doTest _)
else doTest(state)
Expand Down Expand Up @@ -222,15 +238,15 @@ object Interpreter {
}
}
}

def doRun(state: State): Task[State] = {
Tasks.compile(state, project, reporter, excludeRoot = false).flatMap { compiled =>
getMainClass(compiled) match {
case None =>
Task(compiled.mergeStatus(ExitStatus.UnexpectedError))
compileAnd(state, project, reporter, excludeRoot = false) { state =>
getMainClass(state) match {
case None => Task(state.mergeStatus(ExitStatus.RunError))
case Some(main) =>
val args = cmd.args.toArray
val cwd = cmd.cliOptions.common.workingPath
Tasks.run(compiled, project, cwd, main, args)
Tasks.run(state, project, cwd, main, args)
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/main/scala/bloop/engine/tasks/Tasks.scala
Expand Up @@ -94,9 +94,12 @@ object Tasks {
val results = Dag.dfs(results0)
val failures = Compilation.Result.failedProjects(results).distinct
val successes = Compilation.Result.successfulProjects(results)
val newCache = state.results.addResults(successes)
failures.foreach(p => logger.error(s"'${p.name}' failed to compile."))
state.copy(results = newCache)
val newState = state.copy(results = state.results.addResults(successes))
if (failures.isEmpty) newState
else {
failures.foreach(p => logger.error(s"'${p.name}' failed to compile."))
newState.copy(status = ExitStatus.CompilationError)
}
}
}

Expand Down

0 comments on commit e168ca9

Please sign in to comment.