mirror of https://github.com/sbt/sbt.git
Rename some layering related fields/classes
In code review, @eed3si9n suggested that I switch to a more verbose and descriptive naming scheme. In addition to trying to make layers more descriptive, I also made the various layer case objects extend the relevant layers so it's more clear what the layer should look like.
This commit is contained in:
parent
1ca6b97de2
commit
3a211710f9
|
|
@ -8,10 +8,10 @@
|
|||
package sbt
|
||||
|
||||
/**
|
||||
* Represents a ClassLoader layering strategy. By providing an instance of [[LayeringStrategy]],
|
||||
* Represents a ClassLoader layering strategy. By providing an instance of [[ClassLoaderLayeringStrategy]],
|
||||
* users can configure the strategy that they want to use in various sbt tasks, most importantly
|
||||
* [[Keys.run]] and [[Keys.test]]. This setting is only relevant if fork := false in the task for
|
||||
* which we obtain a LayeringStrategy.
|
||||
* which we obtain a ClassLoaderLayeringStrategy.
|
||||
*
|
||||
* ClassLoaders can be composed of multiple ClassLoaders
|
||||
* to form a graph for loading a class. The different portions of the graph may be cached and
|
||||
|
|
@ -62,54 +62,66 @@ package sbt
|
|||
* In general, this should only happen if the user explicitly overrides the thread context
|
||||
* ClassLoader or uses reflection to manipulate classes loaded by different loaders.
|
||||
*/
|
||||
sealed trait LayeringStrategy
|
||||
sealed trait ClassLoaderLayeringStrategy
|
||||
|
||||
/**
|
||||
* Provides instances of [[LayeringStrategy]] that can be used to define the ClassLoader used by
|
||||
* Provides instances of [[ClassLoaderLayeringStrategy]] that can be used to define the ClassLoader used by
|
||||
* [[Keys.run]], [[Keys.test]] or any other task that runs java code inside of the sbt jvm.
|
||||
*/
|
||||
object LayeringStrategy {
|
||||
object ClassLoaderLayeringStrategy {
|
||||
|
||||
/**
|
||||
* Use the default LayeringStrategy for this task.
|
||||
* Use the default ClassLoaderLayeringStrategy for this task.
|
||||
*/
|
||||
case object Default extends LayeringStrategy
|
||||
case object Default extends ClassLoaderLayeringStrategy
|
||||
|
||||
/**
|
||||
* Include all of the dependencies in the loader. The base loader will be the Application
|
||||
* ClassLoader. All classes apart from system classes will be reloaded with each run.
|
||||
*/
|
||||
case object Flat extends LayeringStrategy
|
||||
case object Flat extends ClassLoaderLayeringStrategy
|
||||
|
||||
/**
|
||||
* Add a layer for the runtime jar dependencies.
|
||||
* Add a layer for the scala instance class loader.
|
||||
*/
|
||||
sealed trait RuntimeLayer extends LayeringStrategy
|
||||
|
||||
/**
|
||||
* Add a layer for the runtime jar dependencies.
|
||||
*/
|
||||
case object RuntimeDependencies extends RuntimeLayer
|
||||
|
||||
/**
|
||||
* Add a layer for the test jar dependencies.
|
||||
*/
|
||||
sealed trait TestLayer extends LayeringStrategy
|
||||
|
||||
/**
|
||||
* Add a layer for the test jar dependencies.
|
||||
*/
|
||||
case object TestDependencies extends TestLayer
|
||||
|
||||
/**
|
||||
* Add a layer for the test jar dependencies as well as a layer for the runtime jar dependencies.
|
||||
*/
|
||||
case object Full extends RuntimeLayer with TestLayer
|
||||
sealed trait ScalaInstance extends ClassLoaderLayeringStrategy
|
||||
|
||||
/**
|
||||
* This should indicate that we use a two layer ClassLoader where the top layer is the scala
|
||||
* instance and all of the dependencies and project class paths are included in the search path
|
||||
* of the second layer.
|
||||
*/
|
||||
case object ScalaInstance extends LayeringStrategy
|
||||
case object ScalaInstance extends ScalaInstance
|
||||
|
||||
/**
|
||||
* Add a layer on top of the ScalaInstance layer for the runtime jar dependencies.
|
||||
*/
|
||||
sealed trait RuntimeDependencies extends ScalaInstance
|
||||
|
||||
/**
|
||||
* Add a layer on top of the ScalaInstance layer for the runtime jar dependencies.
|
||||
*/
|
||||
case object RuntimeDependencies extends ScalaInstance with RuntimeDependencies
|
||||
|
||||
/**
|
||||
* Add a layer on top of the ScalaInstance layer for the test jar dependencies.
|
||||
*/
|
||||
sealed trait TestDependencies extends ScalaInstance
|
||||
|
||||
/**
|
||||
* Add a layer on top of the ScalaInstance layer for the test jar dependencies.
|
||||
*/
|
||||
case object TestDependencies extends ScalaInstance with TestDependencies
|
||||
|
||||
/**
|
||||
* Add the TestDependencies layer on top of the RuntimeDependencies layer on top of the
|
||||
* ScalaInstance layer. This differs from TestDependencies in that it will not reload the
|
||||
* runtime classpath. The drawback to using this is that if the test dependencies evict
|
||||
* classes provided in the runtime layer, then tests can fail.
|
||||
*/
|
||||
case object ShareRuntimeDependenciesLayerWithTestDependencies
|
||||
extends ScalaInstance
|
||||
with RuntimeDependencies
|
||||
with TestDependencies
|
||||
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ object Defaults extends BuildCommon {
|
|||
defaultTestTasks(test) ++ defaultTestTasks(testOnly) ++ defaultTestTasks(testQuick) ++ Seq(
|
||||
excludeFilter :== HiddenFileFilter,
|
||||
classLoaderCache := ClassLoaderCache(4),
|
||||
layeringStrategy := LayeringStrategy.Default
|
||||
classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Default
|
||||
) ++ TaskRepository
|
||||
.proxy(GlobalScope / classLoaderCache, ClassLoaderCache(4)) ++ globalIvyCore ++ globalJvmCore
|
||||
) ++ globalSbtCore
|
||||
|
|
@ -813,7 +813,7 @@ object Defaults extends BuildCommon {
|
|||
(fullClasspath in test).value,
|
||||
testForkedParallel.value,
|
||||
(javaOptions in test).value,
|
||||
(layeringStrategy).value
|
||||
(classLoaderLayeringStrategy).value
|
||||
)
|
||||
}
|
||||
).value,
|
||||
|
|
@ -980,7 +980,7 @@ object Defaults extends BuildCommon {
|
|||
fullClasspath.value,
|
||||
testForkedParallel.value,
|
||||
javaOptions.value,
|
||||
layeringStrategy.value
|
||||
classLoaderLayeringStrategy.value
|
||||
)
|
||||
val taskName = display.show(resolvedScoped.value)
|
||||
val trl = testResultLogger.value
|
||||
|
|
@ -1024,7 +1024,7 @@ object Defaults extends BuildCommon {
|
|||
cp,
|
||||
forkedParallelExecution = false,
|
||||
javaOptions = Nil,
|
||||
strategy = LayeringStrategy.Default
|
||||
strategy = ClassLoaderLayeringStrategy.Default
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -1046,7 +1046,7 @@ object Defaults extends BuildCommon {
|
|||
cp,
|
||||
forkedParallelExecution,
|
||||
javaOptions = Nil,
|
||||
strategy = LayeringStrategy.Default
|
||||
strategy = ClassLoaderLayeringStrategy.Default
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -1059,7 +1059,7 @@ object Defaults extends BuildCommon {
|
|||
cp: Classpath,
|
||||
forkedParallelExecution: Boolean,
|
||||
javaOptions: Seq[String],
|
||||
strategy: LayeringStrategy,
|
||||
strategy: ClassLoaderLayeringStrategy,
|
||||
): Initialize[Task[Tests.Output]] = {
|
||||
val runners = createTestRunners(frameworks, loader, config)
|
||||
val groupTasks = groups map {
|
||||
|
|
@ -1091,16 +1091,18 @@ object Defaults extends BuildCommon {
|
|||
case (suite, e) =>
|
||||
e.throwables
|
||||
.collectFirst {
|
||||
case t if t.isInstanceOf[NoClassDefFoundError] && strategy != LayeringStrategy.Flat =>
|
||||
case t
|
||||
if t
|
||||
.isInstanceOf[NoClassDefFoundError] && strategy != ClassLoaderLayeringStrategy.Flat =>
|
||||
t
|
||||
}
|
||||
.foreach { t =>
|
||||
s.log.error(
|
||||
s"Test suite $suite failed with $t. This may be due to the LayeringStrategy"
|
||||
s"Test suite $suite failed with $t. This may be due to the ClassLoaderLayeringStrategy"
|
||||
+ s" ($strategy) used by your task. This issue may be resolved by changing the"
|
||||
+ " LayeringStrategy in your configuration (generally Test or IntegrationTest),"
|
||||
+ "e.g.:\nTest / layeringStrategy := LayeringStrategy.Flat\n"
|
||||
+ "See LayeringStrategy.scala for the full list of options."
|
||||
+ " ClassLoaderLayeringStrategy in your configuration (generally Test or IntegrationTest),"
|
||||
+ "e.g.:\nTest / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat\n"
|
||||
+ "See ClassLoaderLayeringStrategy.scala for the full list of options."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ object Keys {
|
|||
val bgRunMain = inputKey[JobHandle]("Start a provided main class as a background job")
|
||||
val fgRunMain = inputKey[Unit]("Start a provided main class as a foreground job")
|
||||
val bgCopyClasspath = settingKey[Boolean]("Copies classpath on bgRun to prevent conflict.")
|
||||
val layeringStrategy = settingKey[LayeringStrategy]("Creates the classloader layering strategy for the particular configuration.")
|
||||
val classLoaderLayeringStrategy = settingKey[ClassLoaderLayeringStrategy]("Creates the classloader layering strategy for the particular configuration.")
|
||||
|
||||
// Test Keys
|
||||
val testLoader = taskKey[ClassLoader]("Provides the class loader used for testing.").withRank(DTask)
|
||||
|
|
|
|||
|
|
@ -35,15 +35,15 @@ private[sbt] object ClassLoaders {
|
|||
val si = scalaInstance.value
|
||||
val rawCP = data(fullClasspath.value)
|
||||
val fullCP = if (si.isManagedVersion) rawCP else si.allJars.toSeq ++ rawCP
|
||||
val strategy = layeringStrategy.value
|
||||
val strategy = classLoaderLayeringStrategy.value
|
||||
val runtimeCache = (Runtime / classLoaderCache).value
|
||||
val testCache = classLoaderCache.value
|
||||
val tmp = IO.createUniqueDirectory(taskTemporaryDirectory.value)
|
||||
val resources = ClasspathUtilities.createClasspathResources(fullCP, si)
|
||||
|
||||
val raw = strategy match {
|
||||
case LayeringStrategy.Flat => flatLoader(rawCP, interfaceLoader)
|
||||
case s =>
|
||||
case ClassLoaderLayeringStrategy.Flat => flatLoader(rawCP, interfaceLoader)
|
||||
case s =>
|
||||
/*
|
||||
* Create a layered classloader. There are up to four layers:
|
||||
* 1) the scala instance class loader
|
||||
|
|
@ -55,10 +55,11 @@ private[sbt] object ClassLoaders {
|
|||
* and test dependencies, it's important to be able to configure which layers are used.
|
||||
*/
|
||||
val (layerDependencies, layerTestDependencies) = s match {
|
||||
case LayeringStrategy.Full => (true, true)
|
||||
case LayeringStrategy.ScalaInstance => (false, false)
|
||||
case LayeringStrategy.RuntimeDependencies => (true, false)
|
||||
case _ => (false, true)
|
||||
case ClassLoaderLayeringStrategy.ShareRuntimeDependenciesLayerWithTestDependencies =>
|
||||
(true, true)
|
||||
case ClassLoaderLayeringStrategy.ScalaInstance => (false, false)
|
||||
case ClassLoaderLayeringStrategy.RuntimeDependencies => (true, false)
|
||||
case _ => (false, true)
|
||||
}
|
||||
// Do not include exportedProducts in any cached layers because they may change between runs.
|
||||
val exclude = dependencyJars(exportedProducts).value.toSet ++ si.allJars.toSeq
|
||||
|
|
@ -127,8 +128,8 @@ private[sbt] object ClassLoaders {
|
|||
val newLoader =
|
||||
(classpath: Seq[File]) => {
|
||||
val resources = ClasspathUtilities.createClasspathResources(classpath, instance)
|
||||
val classLoader = layeringStrategy.value match {
|
||||
case LayeringStrategy.Flat =>
|
||||
val classLoader = classLoaderLayeringStrategy.value match {
|
||||
case ClassLoaderLayeringStrategy.Flat =>
|
||||
ClasspathUtilities
|
||||
.toLoader(Nil, flatLoader(classpath, new NullLoader), resources, tmp)
|
||||
case _ =>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
> set Test / layeringStrategy := LayeringStrategy.Full
|
||||
> set Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ShareRuntimeDependenciesLayerWithTestDependencies
|
||||
|
||||
> run
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
> set Test / layeringStrategy := LayeringStrategy.Full
|
||||
> set Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ShareRuntimeDependenciesLayerWithTestDependencies
|
||||
|
||||
> run
|
||||
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
# have the sbt.foo.Foo.y method defined.
|
||||
> test
|
||||
|
||||
> set Test / layeringStrategy := LayeringStrategy.TestDependencies
|
||||
> set Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.TestDependencies
|
||||
|
||||
> run
|
||||
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ final class TestFramework(val implClassNames: String*) extends Serializable {
|
|||
+ " using a layered class loader that cannot reach the sbt.testing.Framework class."
|
||||
+ " The most likely cause is that your project has a runtime dependency on your"
|
||||
+ " test framework, e.g. scalatest. To fix this, you can try to set\n"
|
||||
+ "Test / layeringStrategy := new LayeringStrategy.Test(false, true)\nor\n"
|
||||
+ "Test / layeringStrategy := LayeringStrategy.Flat"
|
||||
+ "Test / classLoaderLayeringStrategy := new ClassLoaderLayeringStrategy.Test(false, true)\nor\n"
|
||||
+ "Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat"
|
||||
)
|
||||
None
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue