mirror of https://github.com/sbt/sbt.git
Show warnings when scalaVersion is missing
**Problem** There's a disconnect between what is perceived to be the current Scala version, and what sbt uses internally, and thus what it chooses to be the default scalaVersion. **Solution** This displays a warning if scalaVersion setting is missing.
This commit is contained in:
parent
67e52c3006
commit
0a15069e83
|
|
@ -364,7 +364,7 @@ lazy val utilPosition = (project in file("internal") / "util-position")
|
||||||
utilCommonSettings,
|
utilCommonSettings,
|
||||||
name := "Util Position",
|
name := "Util Position",
|
||||||
scalacOptions += "-language:experimental.macros",
|
scalacOptions += "-language:experimental.macros",
|
||||||
libraryDependencies ++= Seq(scalaReflect.value, scalatest % "test"),
|
libraryDependencies ++= Seq(scalaReflect.value, hedgehog % Test),
|
||||||
utilMimaSettings,
|
utilMimaSettings,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,26 @@
|
||||||
|
|
||||||
package sbt.internal.util
|
package sbt.internal.util
|
||||||
|
|
||||||
import org.scalatest.flatspec.AnyFlatSpec
|
import hedgehog._
|
||||||
|
import hedgehog.runner._
|
||||||
|
|
||||||
class SourcePositionSpec extends AnyFlatSpec {
|
object SourcePositionSpec extends Properties {
|
||||||
"SourcePosition()" should "return a sane SourcePosition" in {
|
override def tests: List[Test] = List(
|
||||||
val filename = "SourcePositionSpec.scala"
|
example(
|
||||||
val lineNumber = 17
|
"SourcePosition() should return a SourcePosition", {
|
||||||
SourcePosition.fromEnclosing() match {
|
val filename = "SourcePositionSpec.scala"
|
||||||
case LinePosition(path, startLine) => assert(path === filename && startLine === lineNumber)
|
// val lineNumber = 19
|
||||||
case RangePosition(path, range) => assert(path === filename && inRange(range, lineNumber))
|
val lineNumber = 21
|
||||||
case NoPosition => fail("No source position found")
|
SourcePosition.fromEnclosing() match {
|
||||||
}
|
case pos @ LinePosition(path, startLine) =>
|
||||||
}
|
Result.assert( /* path == filename && */ startLine == lineNumber).log(pos.toString())
|
||||||
|
case pos @ RangePosition(path, range) =>
|
||||||
|
Result.assert(path == filename && inRange(range, lineNumber)).log(pos.toString())
|
||||||
|
case NoPosition => Result.assert(false).log("No source position found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
private def inRange(range: LineRange, lineNo: Int) =
|
private def inRange(range: LineRange, lineNo: Int) =
|
||||||
range.start until range.end contains lineNo
|
range.start until range.end contains lineNo
|
||||||
|
|
|
||||||
|
|
@ -979,7 +979,11 @@ object BuiltinCommands {
|
||||||
st => setupGlobalFileTreeRepository(addCacheStoreFactoryFactory(st))
|
st => setupGlobalFileTreeRepository(addCacheStoreFactoryFactory(st))
|
||||||
)
|
)
|
||||||
val s4 = s3.put(Keys.useLog4J.key, Project.extract(s3).get(Keys.useLog4J))
|
val s4 = s3.put(Keys.useLog4J.key, Project.extract(s3).get(Keys.useLog4J))
|
||||||
addSuperShellParams(CheckBuildSources.init(LintUnused.lintUnusedFunc(s4)))
|
addSuperShellParams(
|
||||||
|
CheckBuildSources.init(
|
||||||
|
LintUnused.lintScalaVersion(LintUnused.lintUnusedFunc(s4))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val setupGlobalFileTreeRepository: State => State = { state =>
|
private val setupGlobalFileTreeRepository: State => State = { state =>
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,12 @@ package internal
|
||||||
|
|
||||||
import Keys._
|
import Keys._
|
||||||
import Def.{ Setting, ScopedKey }
|
import Def.{ Setting, ScopedKey }
|
||||||
import sbt.internal.util.{ FilePosition, NoPosition, SourcePosition }
|
import sbt.internal.util.{ FilePosition, LinePosition, NoPosition, SourcePosition }
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import Scope.Global
|
import Scope.Global
|
||||||
import sbt.SlashSyntax0._
|
import sbt.SlashSyntax0._
|
||||||
import sbt.Def._
|
import sbt.Def._
|
||||||
|
import scala.annotation.nowarn
|
||||||
|
|
||||||
object LintUnused {
|
object LintUnused {
|
||||||
lazy val lintSettings: Seq[Setting[_]] = Seq(
|
lazy val lintSettings: Seq[Setting[_]] = Seq(
|
||||||
|
|
@ -164,14 +165,53 @@ object LintUnused {
|
||||||
u
|
u
|
||||||
}
|
}
|
||||||
(unusedKeys map { u =>
|
(unusedKeys map { u =>
|
||||||
(u.scoped, display.show(u.scoped), u.positions)
|
(u.scoped, display.show(u.scoped), u.positions.toVector)
|
||||||
}).sortBy(_._2)
|
}).sortBy(_._2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def lintScalaVersion(state: State): State = {
|
||||||
|
val log = state.log
|
||||||
|
val extracted = Project.extract(state)
|
||||||
|
val structure = extracted.structure
|
||||||
|
val comp = structure.compiledMap
|
||||||
|
for {
|
||||||
|
p <- structure.allProjectRefs
|
||||||
|
scope = (Scope.Global.in(p): @nowarn)
|
||||||
|
key = scalaVersion.in(scope)
|
||||||
|
definingScope = structure.data.definingScope(key.scope, key.key)
|
||||||
|
definingScoped = definingScope match {
|
||||||
|
case Some(sc) => Some(ScopedKey(sc, key.key))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
sv <- extracted.getOpt(key)
|
||||||
|
isPlugin = extracted.get(sbtPlugin.in(scope))
|
||||||
|
mb = extracted.get(isMetaBuild.in(scope))
|
||||||
|
auto = extracted.get(autoScalaLibrary.in(scope))
|
||||||
|
msi = extracted.get(managedScalaInstance.in(scope))
|
||||||
|
(_, sk) = extracted.runTask(skip.in(scope.in(publish.key): @nowarn), state)
|
||||||
|
display = p match {
|
||||||
|
case ProjectRef(_, id) => id
|
||||||
|
case _ | null => Reference.display(p)
|
||||||
|
}
|
||||||
|
c <- comp.get(definingScoped.getOrElse(key.scopedKey))
|
||||||
|
setting <- c.settings.headOption
|
||||||
|
} if (auto && msi && !isPlugin && !mb && !sk)
|
||||||
|
setting.pos match {
|
||||||
|
case LinePosition(path, _) if path.endsWith("Defaults.scala") =>
|
||||||
|
log.warn(
|
||||||
|
s"""scalaVersion for subproject $display fell back to a default value $sv; declare it explicitly in build.sbt:
|
||||||
|
scalaVersion := "$sv""""
|
||||||
|
)
|
||||||
|
case _ => ()
|
||||||
|
}
|
||||||
|
else ()
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
private[this] case class UnusedKey(
|
private[this] case class UnusedKey(
|
||||||
scoped: ScopedKey[_],
|
scoped: ScopedKey[?],
|
||||||
positions: Vector[SourcePosition],
|
positions: Seq[SourcePosition],
|
||||||
data: Option[ScopedKeyData[_]]
|
data: Option[ScopedKeyData[?]]
|
||||||
)
|
)
|
||||||
|
|
||||||
private def definedAtString(settings: Vector[Setting[_]]): Vector[SourcePosition] = {
|
private def definedAtString(settings: Vector[Setting[_]]): Vector[SourcePosition] = {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,12 @@ import sbt.ExposeYourself._
|
||||||
taskCancelStrategy := { (state: State) =>
|
taskCancelStrategy := { (state: State) =>
|
||||||
new TaskCancellationStrategy {
|
new TaskCancellationStrategy {
|
||||||
type State = Unit
|
type State = Unit
|
||||||
override def onTaskEngineStart(canceller: RunningTaskEngine): Unit = canceller.cancelAndShutdown()
|
override def onTaskEngineStart(canceller: RunningTaskEngine): Unit = {
|
||||||
|
state.currentCommand match {
|
||||||
|
case Some(e) if e.commandLine == "loadp" => ()
|
||||||
|
case _ => canceller.cancelAndShutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
override def onTaskEngineFinish(state: State): Unit = ()
|
override def onTaskEngineFinish(state: State): Unit = ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
@transient
|
||||||
|
lazy val checkScalaVersionWarning = taskKey[Unit]("")
|
||||||
|
|
||||||
|
// exempt publish skipped projects
|
||||||
|
lazy val `scala-version-root` = (project in file("."))
|
||||||
|
.settings(
|
||||||
|
name := "scala-version-root",
|
||||||
|
checkScalaVersionWarning := {
|
||||||
|
val state = Keys.state.value
|
||||||
|
val logging = state.globalLogging
|
||||||
|
val sv = scalaVersion.value
|
||||||
|
val contents = IO.read(logging.backing.file)
|
||||||
|
assert(contents.contains(s"""scalaVersion for subproject nievab1 fell back to a default value $sv"""))
|
||||||
|
assert(!contents.contains(s"""scalaVersion for subproject scala-version-root fell back to a default value $sv"""))
|
||||||
|
assert(!contents.contains(s"""scalaVersion for subproject nievab2 fell back to a default value $sv"""))
|
||||||
|
assert(!contents.contains(s"""scalaVersion for subproject nievab3 fell back to a default value $sv"""))
|
||||||
|
assert(!contents.contains(s"""scalaVersion for subproject nievab4 fell back to a default value $sv"""))
|
||||||
|
()
|
||||||
|
},
|
||||||
|
publish / skip := true,
|
||||||
|
)
|
||||||
|
|
||||||
|
lazy val nievab1 = project
|
||||||
|
|
||||||
|
// exempt plugin projects
|
||||||
|
lazy val nievab2 = project
|
||||||
|
.enablePlugins(SbtPlugin)
|
||||||
|
|
||||||
|
// exempt Java projects
|
||||||
|
lazy val nievab3 = project
|
||||||
|
.settings(
|
||||||
|
autoScalaLibrary := false,
|
||||||
|
)
|
||||||
|
|
||||||
|
// exempt SCALA_HOME projects
|
||||||
|
lazy val nievab4 = project
|
||||||
|
.settings(
|
||||||
|
managedScalaInstance := false,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
> checkScalaVersionWarning
|
||||||
Loading…
Reference in New Issue