From 9dfe1a840667174a49aabe0513636587dbfc0a5c Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Fri, 21 Jul 2017 16:26:45 +0200 Subject: [PATCH] Allow `.value` on SettingKey inside ifs & lambdas Calling `.value` on a SettingKey doesn't trigger any execution and doesn't have any side effect, so we can safely allow calls to `.value` inside conditionals and lambdas. Fixes #3299 --- .../main/scala/sbt/std/TaskLinterDSL.scala | 11 ++++++---- .../src/test/scala/sbt/std/TaskPosSpec.scala | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/main-settings/src/main/scala/sbt/std/TaskLinterDSL.scala b/main-settings/src/main/scala/sbt/std/TaskLinterDSL.scala index af691f165..732643a60 100644 --- a/main-settings/src/main/scala/sbt/std/TaskLinterDSL.scala +++ b/main-settings/src/main/scala/sbt/std/TaskLinterDSL.scala @@ -1,5 +1,6 @@ package sbt.std +import sbt.SettingKey import sbt.internal.util.ConsoleAppender import sbt.internal.util.appmacro.{ Convert, Converted, LinterDSL } @@ -62,10 +63,12 @@ abstract class BaseTaskLinterDSL extends LinterDSL { case ap @ Apply(TypeApply(Select(_, nme), tpe :: Nil), qual :: Nil) => val shouldIgnore = uncheckedWrappers.contains(ap) val wrapperName = nme.decodedName.toString - if (!shouldIgnore && isTask(wrapperName, tpe.tpe, qual)) { - val qualName = - if (qual.symbol != null) qual.symbol.name.decodedName.toString - else ap.pos.lineContent + val (qualName, isSettingKey) = + Option(qual.symbol) + .map(sym => (sym.name.decodedName.toString, sym.info <:< typeOf[SettingKey[_]])) + .getOrElse((ap.pos.lineContent, false)) + + if (!isSettingKey && !shouldIgnore && isTask(wrapperName, tpe.tpe, qual)) { if (insideIf && !isDynamicTask) { // Error on the use of value inside the if of a regular task (dyn task is ok) ctx.error(ap.pos, TaskLinterDSLFeedback.useOfValueInsideIfExpression(qualName)) diff --git a/main-settings/src/test/scala/sbt/std/TaskPosSpec.scala b/main-settings/src/test/scala/sbt/std/TaskPosSpec.scala index 17bc85a9f..451ed2bf7 100644 --- a/main-settings/src/test/scala/sbt/std/TaskPosSpec.scala +++ b/main-settings/src/test/scala/sbt/std/TaskPosSpec.scala @@ -150,4 +150,25 @@ class TaskPosSpec { avoidDCE } } + + locally { + import sbt._ + import sbt.Def._ + val foo = settingKey[String]("") + val condition = true + val baz = Def.task[String] { + // settings can be evaluated in a condition + if (condition) foo.value + else "..." + } + } + + locally { + import sbt._ + import sbt.Def._ + val foo = settingKey[String]("") + val baz = Def.task[Seq[String]] { + (1 to 10).map(_ => foo.value) + } + } }